1.根据数字二级制表示中1的个数的排序问题
**题目描述:**给你一个整数数组 arr 。请你将数组中的元素按照其二进制表示中数字 1 的数目升序排序。
如果存在多个数字二进制中 1 的数目相同,则必须将它们按照数值大小升序排列。
请你返回排序后的数组。
提示:
1 <= arr.length <= 500
0 <= arr[i] <= 10^4
示例一:
输入:arr = [0,1,2,3,4,5,6,7,8]
输出:[0,1,2,4,8,3,5,6,7]
解释:[0] 是唯一一个有 0 个 1 的数。
[1,2,4,8] 都有 1 个 1 。
[3,5,6] 有 2 个 1 。
[7] 有 3 个 1 。
按照 1 的个数排序得到的结果数组为 [0,1,2,4,8,3,5,6,7]
示例二:
输入:arr = [1024,512,256,128,64,32,16,8,4,2,1]
输出:[1,2,4,8,16,32,64,128,256,512,1024]
解释:数组中所有整数二进制下都只有 1 个 1 ,所以你需要按照数值大小将它们排序。
示例三:
输入:arr = [10000,10000]
输出:[10000,10000]
题解:
这个问题的第一个重点是,统计一下每个数二进制中1的个数,有两种方法:一,暴力解法,不断进行除&于操作:
int count=0; //统计1的个数
while(x){
count+=x%2;
x/=2;
}
//朴素的二进制求法,只需要将每二进制数的每一位进行相加求和,最后就是1的个数
二,递推预处理:定义 bit[i]作为 数字i的二进制数中1的个数,则写出递推式:
bit[i]=b[i>>1]+(i&1)
其中,i>>1是i右移一位,i&1 可以得到i的二进制数的最低为是0 or 1
for (int i = 1;i <= 10000; ++i) {
bit[i] = bit[i>>1] + (i & 1);
}
可以得到从1到10000所有整数二进制数1的个数。
**在可以求得二进制数1的个数后,**接下来就是排序的问题了,只需要对sort函数改写一下排序规则:
sort(arr.begin(),arr.end(),[&](int x,int y){
if (bit[x] < bit[y]) {//从小到大
return true;
}
if (bit[x] > bit[y]) {
return false;
}
return x < y; //当二进制数中1的个数相等时,按他们本身大小升序排序
});
完整代码:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int get(int x){
int res = 0;
while (x) {
res += (x % 2);
x /= 2;
}
return res;
}
int main() {
vector<int> arr;
int x;
while (cin>>x)
{
arr.push_back(x);
}
vector<int> bit(10001, 0);
//暴力解法
for (auto x: arr) {//类似迭代器,依次得到arr中的值赋给x
bit[x] = get(x);
}
/*
//位运算递归
for (int i = 1;i <= 10000; ++i) {
bit[i] = bit[i>>1] + (i & 1);
}
*/
//改写排序规则:
sort(arr.begin(),arr.end(),[&](int x,int y){
if (bit[x] < bit[y]) {
return true;
}
if (bit[x] > bit[y]) {
return false;
}
return x < y;
});
for(auto p:arr)cout<<p<<" ";
return 0;
}