leetcode刷题6

今天刷的题是LeetCode的第78题,子集。题目的要求是:给定一个不含相同元素的数组,要求输出所有的子集。该题也是没有思路,看的别人的答案写的代码

目前通过参阅别人的解答思路,掌握了两种比较好的解决方法。第一种是位运算。这个解决方法很有意思,就是每个元素其实都是两种状态,在子集中和不在子集中,那么对应的是二进制中的1和0。一个包含n个元素的数组,其子集的个数为2的n次方。将数字转化为二进制,位为1的添加到子集中。如下思路所示。

* 1 2 3
* 0 0 0 -> [ ]
* 0 0 1 -> [ 3]
* 0 1 0 -> [ 2 ]
* 0 1 1 -> [ 2 3]
* 1 0 0 -> [1 ]
* 1 0 1 -> [1 3]
* 1 1 0 -> [1 2 ]
* 1 1 1 -> [1 2 3]
具体的代码如下所示:
public static List<List<Integer>> binaryBit(int[] nums) {
        /**
         * 位操作:数组中的元素,有两个状态,在子数组中和不在子数组中。1代表在,0代表不在
         * 1 2 3
         * 0 0 0 -> [     ]
         * 0 0 1 -> [    3]
         * 0 1 0 -> [  2  ]
         * 0 1 1 -> [  2 3]
         * 1 0 0 -> [1    ]
         * 1 0 1 -> [1   3]
         * 1 1 0 -> [1 2  ]
         * 1 1 1 -> [1 2 3]
         */
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        int len=1<<nums.length;
        for (int i = 0; i < len; i++) {
            List<Integer> sub = new ArrayList<Integer>();
            for (int j = 0; j < nums.length; j++)
                if (((i >> j) & 1) == 1) {
                    sub.add(nums[j]);
                }
            res.add(sub);
        }
        return res;
    }

第二个解决方法也很巧妙。首先考虑问题规模很小的情况,当只有一个元素时,其子集分别是本身和空集。当两个元素时,分别在原有子集的基础上,添加该元素,再新增子集。具体的代码如下所示:

public static List<List<Integer>> leetcode78(int[] nums){
        // 如果将问题缩小到一个元素,那么就是两种情况,空集合本身
        // 此时,再挨个往子集里添加新的元素
        List<List<Integer>> result=new ArrayList<>();
        int n = nums.length;
        result.add(new ArrayList<>());
        for (int i = 0; i <n ; i++) {
            int length=result.size();
            for (int j = 0; j <length ; j++) {
                List<Integer> list=new ArrayList<>(result.get(j));
                list.add(nums[i]);
                result.add(list);
            }
        }
        return result;
    }

 

posted @ 2019-08-11 16:00  刘云生  阅读(141)  评论(0编辑  收藏  举报