leetcode 之 1356. 根据数字二进制下 1 的数目排序

140 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情

题目描述

1356. 根据数字二进制下 1 的数目排序 - 力扣(LeetCode)

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

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

请你返回排序后的数组。

 

示例 1:

输入: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:

输入: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:

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

示例 4:

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

示例 5:

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

提示:

  • 1 <= arr.length <= 500
  • 0 <= arr[i] <= 10^4

思路分析

整体思路:

  1. 先给数组arr排序;
  2. 用与运算计算出每个数字在二进制下的1的数目;
  3. 根据二进制下的1的数目(从小到大)给每个数字进行排序; 步骤:
  4. 声明cnt变量, 给每个数字在二进制下的1的数目进行计数;
  5. 声明num变量, 在进行数字交换时使用;
  6. 声明temp数组, 记录每个数字在二进制下的1的数目;
  7. 声明index数组, 记录每个数字在arr数组中的索引值;
  8. 用快速排序算法给arr数组排序 (目的是为了在后面的插入排序中, 当二进制下1的数目相同时, 实现按照数值大小给数字进行升序排序);
  9. for循环遍历一遍排序后的数组arr, 在遍历过程中, 通过与运算计算出每个数字在二进制下的1的数目, 同时放入temp数组中;
  10. 使用插入排序算法对temp数组中的值进行排序, 并将排序后的值在temp数组中的索引值记录在index数组中;
  11. 将index数组记录的索引值替换成该索引值对应到arr数组中的值, 即将索引值替换成arr数组中的原数字;
  12. 最后返回index数组即可;

AC 代码

class Solution {
    public int[] sortByBits(int[] arr) {
        int len = arr.length;
        quickSort(arr,0,len-1);//先排序
        int[] temp = new int[len];//temp数组记录每个数字在二进制下的1的数目
        int cnt = 0;
        int num = 0;
        for(int i=0;i<arr.length;i++){//for循环计算每个数字在二进制下的1的数目
            cnt = 0;
            num = arr[i];
            while(num!=0){
                cnt++;
                num = num&(num-1);//与运算计算每个数字在二进制下的1的个数
            }
            temp[i] = cnt;
        }
        int[] index = new int[len];//index数组记录的是排序后, 每个数字在原数组arr中对应的索引下标
        int j=0;
        for(int i=0;i<len;i++){//插入排序算法, 给每个数字按照二进制下的1的个数排序
            j=i;
            num = temp[i];
            while(j-1>=0&&temp[index[j-1]]>num){
                index[j] = index[j-1];
                j--;
            }
            index[j] = i;
        }
        for(int i=0;i<len;i++){//将index数组记录的索引值替换成arr数组中对应的数字
            index[i] = arr[index[i]];
        }
        return index;
    }
    public void quickSort(int[] arr, int left, int right){//快速排序
        int l=left;
        int r=right;
        int pivot = arr[(l+r)/2];
        int temp = 0;
        while(l<r){
            while(arr[l]<pivot){
                l++;
            }

            while(arr[r]>pivot){
                r--;
            }
            if(l>=r){
                break;
            }
            temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;

            if(arr[l]==pivot){
                r--;
            }
            if(arr[r]==pivot){
                l++;
            }
        }
        if(l==r){
            l++;
            r--;
        }
        if(left<r){
            quickSort(arr,left,r);
        }
        if(l<right){
            quickSort(arr,l,right);
        }
    }
}