0%

根据数字二进制下1的数目排序

题目地址

题目名称:根据数字二进制下1的数目排序

难度:

题目描述:

给你一个整数数组 arr 。请你将数组中的元素按照其二进制表示中数字 1 的数目升序排序。

如果存在多个数字二进制中 1 的数目相同,则必须将它们按照数值大小升序排列。

请你返回排序后的数组。

示例1:

1
2
3
4
5
6
7
输入: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]

示例2:

1
2
3
输入:-123输入: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 ,所以你需要按照数值大小将它们排序。

示例3:

1
2
输入:arr = [10000,10000]
输出:[10000,10000]

示例4:

1
2
输入:arr = [2,3,5,7,11,13,17,19]
输出:[2,3,5,17,7,11,13,19]

示例5:

1
2
输入:arr = [10,100,1000,10000]
输出:[10,100,10000,1000]

提示:

  • 1 <= arr.length <= 500
  • 0 <= arr[i] <= 10^4
🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️解题过程🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️
解题过程:

思路:

最直观的解法,遍历数组arr,对每一个元素计算二进制表示中1的个数,用一个数组存储相应的个数,然后冒泡排序,最会返回arr

c++代码:(执行104ms,击败5.42%,内存10.2M,击败30.68%)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution {
public:
vector<int> sortByBits(vector<int>& arr) {
vector<int> num;
int bit_num;
int i,j,tmp;
//得到arr数组中每个元素二进制中1的个数
for(i=0;i<arr.size();++i){
bit_num=0;
//计算二进制中1的个数
tmp=arr[i];
while(tmp){
if(tmp & 1){
++bit_num;
}
tmp>>=1;//右移1位
}
num.push_back(bit_num);
}
//对num容器中元素冒泡排序,还可以调用sort方法排序?
for(i=0;i<num.size();++i){
for(j=0;j<num.size()-i-1;++j){
//二进制中1的数目前者比后者大或者数目相同但前者数值大,交换位置
if(num[j]>num[j+1] || (num[j]==num[j+1] && arr[j]>arr[j+1])){
tmp=num[j];
num[j]=num[j+1];
num[j+1]=tmp;
//arr数组排序
tmp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=tmp;
}
}
}
return arr;
}
};
💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎官 方 题 解💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎
官方题解:

前言

题目本身很简单,只要调用系统自带的排序函数,然后自己改写一下排序规则即可,所以这里主要讲讲如何计算数字二进制下 1 的个数 。

方法一:暴力(执行20ms,击败87%,内存14M,击败5.04%)

对每个十进制的数转二进制的时候统计一下 1 的个数即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public:
int get(int x){
int res = 0;
while (x) {
res += (x % 2);
x /= 2;
}
return res;
}
vector<int> sortByBits(vector<int>& arr) {
vector<int> bit(10001, 0);
for (auto x: arr) {
bit[x] = get(x);
}
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;
});
return arr;
}
};

复杂度分析

  • 时间复杂度:$O(nlogn)$,其中 $n$ 为整数数组 arr 的长度。
  • 空间复杂度:$O(n)$,其中 $n$ 为整数数组 arr 的长度。

方法二:递推预处理(执行16M,击败90.64%,内存14M,击败5.14%)
我们定义 $bit[i]$ 为数字 $i$ 二进制表示下数字 1 的个数,则可以列出递推式:

所以我们线性预处理 $bit$ 数组然后去排序即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
vector<int> sortByBits(vector<int>& arr) {
vector<int> bit(10001, 0);
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;
});
return arr;
}
};

复杂度分析

  • 时间复杂度:$O(nlogn)$,其中 $n$ 为整数数组 arr 的长度。
  • 空间复杂度:$O(n)$,其中 $n$ 为整数数组 arr 的长度。
🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓知 识 点🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓
知识点:
  • 整数二进制表示中1的个数计算
  • 调用系统排序函数,修改排序规则
⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳总 结⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳
总结:

官方题解是采用了空间换时间的做法,虽然执行用时很少,但是内存消耗太高了。在成员函数中重写sort函数排序规则这是我没想到的,学到了🤩

------------- THE END! THANKS! -------------