题目
给你一个整数数组 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]
分析
首先我们要将数组中的每个元素其中包含的1的个数求出来,然后根据1的个数大小去进行排序。
之前做“按照频率将数组升序排序”这道题的时候,学到了可以自定义排序一个数组,那么我们也可以在这道题上面自定义排序。
代码
使用Arrays.sort():
public int[] sortByBits(int[] arr) {
HashMap<Integer, Integer> map = new HashMap<>();
Integer[] ans = new Integer[arr.length];
for (int i = 0; i < arr.length; i++) {
ans[i] = arr[i];
int count = 0;
char[] temp = Integer.toBinaryString(arr[i]).toCharArray();
for (int j = 0; j < temp.length; j++) {
if (temp[j] == '1') {
count++;
}
}
map.put(arr[i], count);
}
Arrays.sort(ans, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
if (map.get(o1).equals(map.get(o2))) {
return o1 - o2;
} else if (map.get(o1) > map.get(o2)) {
return 1;
} else {
return -1;
}
}
});
for (int i = 0; i < arr.length; i++) {
arr[i] = ans[i];
}
return arr;
}
}
在调用Arrays.sort()进行自定义排序的时候,我们需要注意将int[] 型——>Integer[] 型,这样才能进行比较。
void java.util.Arrays.sort(Integer[] a, Comparator<? super Integer> c)
通过循环,我们进行复制arr数组和统计每个元素中1的个数(用HashMap进行存储);
自定义排序的时候,我们需要通过map.get()去获得每个元素含1的个数,两两进行比较:
- map.get(o1).equals(map.get(o2)),说明二者含1的个数相等,升序排序——返回o1-o2(详见下面);
- map.get(o1) > map.get(o2),说明前面的数含1个数大于后面的,要进行位置交换——返回 1;
- map.get(o1) < map.get(o2),前面的数含1的个数小于后面的,符合升序,不需要交换位置——返回-1。
我们需要注意
Compare函数:
Compares its two arguments for order. Returns a negative integer,zero, or a positive integer as the first argument is less than, equalto, or greater than the second.
1:前面的数>后面的数,是降序(从大到小)排列,如果想要改为升序排列,就需要返回1
-1:前面的数<后面的数,是升序(从小到大)排列,不改变位置就返回-1;
0:二者相等,不进行交换,也就不排序。但是要根据题目来判断返回什么。比如这道题说的是,对含1 个数相同的元素进行升序排列,但是很重要的一点:HashMap是乱乱序!!我知道它很乱,但是没有想到这么乱,他不会根据你加入元素的顺序来排列的,它自有规则(hashcode)。所以数组是无序的,不能直接返回0。这里为了保证升序排列,要返回o1-o2。
- return 0:不交换位置,不排序
- return 1:交换位置
- return -1:不交换位置
- return o1-o2:升序排列
- return o2-o1:降序排列
使用Collections.sort()
public int[] sortByBits2(int[] arr) {
List<Integer> list = new ArrayList<Integer>();
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
list.add(arr[i]);
int count = 0;
char[] temp = Integer.toBinaryString(arr[i]).toCharArray();
for (int j = 0; j < temp.length; j++) {
if (temp[j] == '1') {
count++;
}
}
map.put(arr[i], count);
}
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
if (map.get(o1) == map.get(o2)) {
return o1-o2;
} else {
return map.get(o1) - map.get(o2);
}
}
});
for (int i = 0; i < list.size(); i++) {
arr[i] = list.get(i);
}
return arr;
}
做题反思
首先,我要道歉,对不起LeetCode,对不起简单题,我太丢脸了,我太不尊重easy了,我以后一定好好学习,好好思考,认真对待。
然后就是:注意细节!!
end.