难度简单
给你一个整数数组 arr
。请你将数组中的元素按照其二进制表示中数字 1 的数目升序排序。
如果存在多个数字二进制中 1 的数目相同,则必须将它们按照数值大小升序排列。
请你返回排序后的数组。
思路一:
对原数组排序,统计数组中各数字的二进制中包含 1 的个数,保存到map中并以此进行排序。
vector<int> sortByBits(vector<int>& arr) {
unordered_map<int, vector<int>> M;
vector<int> ans;
sort(arr.begin(),arr.end());
int MAX=0;
for(auto index:arr){
if(index>MAX) MAX=index;
M[numOfOne(index)].push_back(index);
}
for(int i=0;i<=MAX;++i){
if(!M[i].size()) continue;
for(auto data:M[i]){
ans.push_back(data);
}
}
return ans;
}
// 统计数字二进制表示中 1 的个数 针对数据按位进行比较,时间复杂度为O(m)
// 也可以采用函数 int num = __builtin_popcount(index); 它使用一张基于表的方法来进行位搜索,因此这个操作的执行效率很高
int numOfOne(int& index){
int res=0; // 1的数量
int tem=1;
while(tem<=index){
if(index & tem) res++;
tem<<=1;
}
return res;
}
思路二:采用 sort 函数的第三个参数,直接进行处理。
sort函数两参数使用时,默认为从小到大排序,可以使用第三个参数,重新规定排序规则,把数字的二进制表示中 1 的个数和数字的原本大小作为排序规则。
函数原型:void sort (RandomAccessIterator first, RandomAccessIterator last); // 默认从小到大排序
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp); // 按照 comp 规定的排序规则排序
comp 是二进制函数,接受 first~last 之间的两个元素作为参数,返回 bool 值,false表示两者交换位置,true表示两者不需要交换位置
[&](int x,int y){ // 构造了一个引用参量的匿名函数 用于实现交换规则
int m = __builtin_popcount(x), n = __builtin_popcount(y); // 计算数字的二进制表示中有多少个 1
return m == n? x<y : m<n;
}
vector<int> sortByBits(vector<int>& arr) {
sort(arr.begin(),arr.end(),[&](int x,int y){
int m = __builtin_popcount(x), n = __builtin_popcount(y); // 计算数字的二进制表示中有多少个 1
return m == n? x<y : m<n;
});
return arr;
}