注:这个题目有序的意思是"升序"
解法一:bubblesort O(nlogn)
核心思想:冒泡每次会将一个数归位到最后的位置上,所以我们如果碰到无法向右交换的数字,即可return false
cpp
class Solution {
public:
// 返回一个十进制数字对应的二进数中1的个数
int getnum(int a){
int res = 0;
while(a){
if(a & 1 == 1) res ++;
a >>= 1;
}
return res;
}
bool check(vector<int> & nums){
int f1 = 1;
for(int i = 0; i < nums.size() - 1; i ++){ // 升序有序(默认?)
if(nums[i] > nums[i + 1]){
f1 = 0;
break;
}
}
return f1;
}
bool canSortArray(vector<int>& nums) {
bool fg = true;
int n = nums.size();
unordered_map<int, int> mp;
// 预处理出来所有的数字对应的二进制数字
for(auto v : nums){
int b = getnum(v);
mp.insert({v, b});
cout << v << " " << b << endl;
}
if(check(nums)) return fg; // 原本是直接有序的
else{
for(int i = 0; i < n; i ++){
for(int j = 0; j < n - i - 1; j ++){
// 每次都会将一个数字归位
if(nums[j] > nums[j + 1]){
if(mp[nums[j]] == mp[nums[j + 1]])
swap(nums[j], nums[j + 1]);
else
return false;
}
}
}
}
return fg;
}
};
解法二:模拟分组,指针单向扫描一遍O(N)
关键是发现相同元素进行分组,维护这个分组只需要指针i和premax两个信息, 然后切换至下一组时用curmax更新premax。要求本组的每一个元素都要大于前一个组的max值即可,否则需要跨组交换(不是一个组无法进行)
cpp
class Solution {
public:
int getnum(int a){
int res = 0;
while(a){
if(a & 1) res ++;
a >>= 1;
}
return res;
}
bool canSortArray(vector<int>& nums) {
int curmax = 0, premax = 0;
// 要求当前组的每一个元素都要大于前一个组的最大值即可
for(int i = 0; i < nums.size(); ){
curmax = 0; // 每次进入一个新的组,都要初始化为0
int ones = getnum(nums[i]);
while(i < nums.size() && getnum(nums[i]) == ones){ // 遍历本组
if(nums[i] > curmax) curmax = nums[i]; // 记录curmax用于初始化下一组的premax
if(nums[i] < premax) return false; // 见第一行的要求
i ++;
}
premax = curmax; // 进入下一组前设置好premax
}
return true;
}
};