和算法渣一起练习--利用位运算,轻轻松松就能解决数学里的子集问题 (2)

但是计算机要怎么来对应呢?我们可以遍历我们的数组,来依次检查每个元素对应的二进制bit是否为1,如果为1,说明该元素被选中了,加到结果集中,比如遍历到1这个元素的时候,它在数组中的下标为0(数组下标从0开始别忘)。

那么,那么它在110这个二进制中,它是存储在哪个bit呢?是存储在最高位的bit的。

和算法渣一起练习--利用位运算,轻轻松松就能解决数学里的子集问题

所以,对于数组[1,2,3]中的第一个值1,其对应了二进制中的高位,需要右移n-1(n为数组长度,这里为3),即右移2位后进行计算;

对于数组[1,2,3]中的第二个值2,其对应了二进制中的第1位,需要右移3-2位,即右移1位。

对于数组中第三个值3,其对应了二进制中的第0位,需要右移3-3位,即不需移位。

好了,接下来,我们转换为代码:

class Solution { public static void main(String[] args) { List<List<Integer>> set = subsets(new int[]{1, 2, 3}); for (List<Integer> integers : set) { // System.out.println(integers); } } public List<List<Integer>> subsets(int[] nums) { if (nums == null || nums.length == 0){ List<Integer> list = new ArrayList<Integer>(); List<List<Integer>> result = new ArrayList<List<Integer>>(); result.add(list); return result; } int arraySize = 1 << nums.length; List<List<Integer>> result = new ArrayList<List<Integer>>(arraySize); for (int i = 0; i < arraySize; i++){ // leetcode提交时,记得注释掉,打印比较费时间 System.out.println(Integer.toBinaryString(i)); // 用来存放当前选项下的结果集 List<Integer> list = new ArrayList<Integer>(); // 遍历数组 for (int j = 0; j < nums.length; j++){ // 找到要右移的位数; 假设为第一个数,则需要右移2位 int moveStep = nums.length - j - 1; // 判断该bit是否为1,为1表示该数被选中 if (((i >> moveStep) & 1) == 1){ list.add(nums[j]); } } // 打印本选项下的结果,leetcode提交时,记得注释掉,打印比较费时间 System.out.println("选中的子集为:" + list); result.add(list); } return result; } }

执行结果如下:

0 选中的子集为:[] 1 选中的子集为:[3] 10 选中的子集为:[2] 11 选中的子集为:[2, 3] 100 选中的子集为:[1] 101 选中的子集为:[1, 3] 110 选中的子集为:[1, 2] 111 选中的子集为:[1, 2, 3] 小结

这个题还有很多其他思路,什么回溯之类的,鉴于我也还没搞懂,就先不写了(写不出来啊。。。)。

算法渣渣的算法之旅,希望能坚持下去!

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygsps.html