leetcode.1356. 根據數字二進位制下 1 的數目排序

怪我冷i發表於2020-11-06

題目

給你一個整數陣列 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的個數可以分別獲取每個二進位制位數,然後再統計其1的個數,此方法效率比較低。這裡介紹另外一種高效的方法,同樣以 34520 為例,我們計算其 a &= (a-1)的結果:

第一次:計算前:1000 0110 1101 1000 計算後:1000 0110 1101 0000 第二次:計算前:1000 0110 1101 0000 計算後:1000 0110 1100 0000 第二次:計算前:1000 0110 1100 0000 計算後:1000 0110 1000 0000 我們發現,每計算一次二進位制中就少了一個 1 因此可以用此方法求1的個數,即下面的count_one函式。

程式碼

int count_one(int a){
    int cnt=0;
    while(a) a=a&(a-1),cnt++;
    return cnt;
}
bool cmp(int a,int b){
    int numa=count_one(a),numb=count_one(b);
    return numa!=numb?numa<numb:a<b;
}
class Solution {
public:
    vector<int> sortByBits(vector<int>& arr) {
        sort(arr.begin(),arr.end(),cmp);
        return arr;
    }
};

或者

class Solution {
private:
    static int count_one(int a){
        int cnt=0;
        while(a) a=a&(a-1),cnt++;
        return cnt;
    }
    static bool cmp(int a,int b){
        int numa=count_one(a),numb=count_one(b);
        return numa!=numb?numa<numb:a<b;
    }
public:
    vector<int> sortByBits(vector<int>& arr) {
        sort(arr.begin(),arr.end(),cmp);
        return arr;
    }
};

java版 ,暴力法

package sort_integers_by_the_number_of_1_bits;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Solution1 {
	
    public int[] sortByBits(int[] arr) {
        int[] bit = new int[10001];
        //對每個十進位制的數轉二進位制的時候統計一下 1 的個數
        List<Integer> list = new ArrayList<Integer>();
        for (int x : arr) {
            list.add(x);
            bit[x] = get(x);
        }
        Collections.sort(list, new Comparator<Integer>() {
            public int compare(Integer x, Integer y) {
                if (bit[x] != bit[y]) {
                    return bit[x] - bit[y];
                } else {
                    return x - y;
                }
            }
        });
        //返回結果
        for (int i = 0; i < arr.length; ++i) {
            arr[i] = list.get(i);
        }
        return arr;
    }

    //對每個十進位制的數轉二進位制的時候統計一下 1 的個數
    public int get(int x) {
        int res = 0;
        print(x);
        while (x != 0) {
            res += x % 2;
            x /= 2;
        }
        return res;
    }
    
    
    
    private void print(int x) {
    	System.out.println("##### x="+x+" #####");
    	int res = 0;
        while (x != 0) {
        	int tmp1 = x;
        	int tmp2 = x % 2;
        	res += tmp2;
        	System.out.printf("%5d%s%2d = %d,",tmp1," %",2,tmp2);
        	System.out.printf("%5d%s%2d = %d\n",tmp1," /",2,(x/=2));
        }
        System.out.println("res="+res);
	}

	public static void main(String[] args) {
		int[] arr = {0,1,2,3,4,5,6,7,8,13,10000};
		int[] res = new Solution1().sortByBits(arr);
		System.out.println("原陣列 "+Arrays.toString(arr));
		System.out.println("排序後 "+Arrays.toString(res));
	}
}

輸出

##### x=0 #####
res=0
##### x=1 #####
    1 % 2 = 1,    1 / 2 = 0
res=1
##### x=2 #####
    2 % 2 = 0,    2 / 2 = 1
    1 % 2 = 1,    1 / 2 = 0
res=1
##### x=3 #####
    3 % 2 = 1,    3 / 2 = 1
    1 % 2 = 1,    1 / 2 = 0
res=2
##### x=4 #####
    4 % 2 = 0,    4 / 2 = 2
    2 % 2 = 0,    2 / 2 = 1
    1 % 2 = 1,    1 / 2 = 0
res=1
##### x=5 #####
    5 % 2 = 1,    5 / 2 = 2
    2 % 2 = 0,    2 / 2 = 1
    1 % 2 = 1,    1 / 2 = 0
res=2
##### x=6 #####
    6 % 2 = 0,    6 / 2 = 3
    3 % 2 = 1,    3 / 2 = 1
    1 % 2 = 1,    1 / 2 = 0
res=2
##### x=7 #####
    7 % 2 = 1,    7 / 2 = 3
    3 % 2 = 1,    3 / 2 = 1
    1 % 2 = 1,    1 / 2 = 0
res=3
##### x=8 #####
    8 % 2 = 0,    8 / 2 = 4
    4 % 2 = 0,    4 / 2 = 2
    2 % 2 = 0,    2 / 2 = 1
    1 % 2 = 1,    1 / 2 = 0
res=1
##### x=13 #####
   13 % 2 = 1,   13 / 2 = 6
    6 % 2 = 0,    6 / 2 = 3
    3 % 2 = 1,    3 / 2 = 1
    1 % 2 = 1,    1 / 2 = 0
res=3
##### x=10000 #####
10000 % 2 = 0,10000 / 2 = 5000
 5000 % 2 = 0, 5000 / 2 = 2500
 2500 % 2 = 0, 2500 / 2 = 1250
 1250 % 2 = 0, 1250 / 2 = 625
  625 % 2 = 1,  625 / 2 = 312
  312 % 2 = 0,  312 / 2 = 156
  156 % 2 = 0,  156 / 2 = 78
   78 % 2 = 0,   78 / 2 = 39
   39 % 2 = 1,   39 / 2 = 19
   19 % 2 = 1,   19 / 2 = 9
    9 % 2 = 1,    9 / 2 = 4
    4 % 2 = 0,    4 / 2 = 2
    2 % 2 = 0,    2 / 2 = 1
    1 % 2 = 1,    1 / 2 = 0
res=5
原陣列 [0, 1, 2, 4, 8, 3, 5, 6, 7, 13, 10000]
排序後 [0, 1, 2, 4, 8, 3, 5, 6, 7, 13, 10000]

相關文章