题目地址
题目名称:根据数字二进制下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; for(i=0;i<arr.size();++i){ bit_num=0; tmp=arr[i]; while(tmp){ if(tmp & 1){ ++bit_num; } tmp>>=1; } num.push_back(bit_num); } for(i=0;i<num.size();++i){ for(j=0;j<num.size()-i-1;++j){ 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; 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函数排序规则这是我没想到的,学到了🤩