LeetCode1356.根据数字二进制下1的数目排序(Java+自定义排序)

题目

给你一个整数数组 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的个数,两两进行比较:

  1. map.get(o1).equals(map.get(o2)),说明二者含1的个数相等,升序排序——返回o1-o2(详见下面);
  2. map.get(o1) > map.get(o2),说明前面的数含1个数大于后面的,要进行位置交换——返回 1;
  3. 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.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值