Woodyiiiiiii / LeetCode

My private record of Leetcode solution

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

LeetCode 78. Subsets

Woodyiiiiiii opened this issue · comments

Given a set of distinct integers, nums, return all possible subsets (the power set).

Note: The solution set must not contain duplicate subsets.

Example:

Input: nums = [1,2,3]
Output:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

这道题显然不能纯粹使用暴力法,因为我们不知道到底有多少可能,只能观察数据找规律。
实际上每次存进线性表,可以看作在线性表的元素基础上加上新的nums数组中的元素,再存入线性表中。比如nums = {1, 2},一开始线性表初始化为[[]],元素只有一个,取出来加上元素1等于[1],再存入线性表中,线性表变为[[], [1]],同理,加入2后变为[[], [1], [2], [1, 2]]。

//C++ solution:
class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int> > res(1);
        sort(nums.begin(), nums.end());
        for (int i = 0; i < nums.size(); ++i) {
            int size = res.size();
            for (int j = 0; j < size; ++j) {
                res.push_back(res[j]);
                res.back().push_back(nums[i]);
            }
        }
        return res;
    }
};
//Java solution:
class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        int n = nums.length;
        List<List<Integer>> res = new LinkedList();
        if (n == 0) return res;
        Arrays.sort(nums);
        res.add(new LinkedList<Integer>());
        for (int i = 0; i < n; ++i) {
            int size = res.size();
            for (int j = 0; j < size; ++j) {
                res.add(new LinkedList<>(res.get(j)));
                res.get(res.size() - 1).add(nums[i]);
            }
        }
        return res;
    }
}

注意Java跟C++的解法不同,因为Java容器类太不方便了。取出元素时使用get方法,然而实际上因为Java的值传递,我们并没有声明新的空间,存入线性表中的元素内存地址是一样的,所以如果按照C++的解法,在向某元素添加新的nums里的数值时,会对原本的线性表元素产生影响。比如,[[1]]中我想加入数值2,取出1加上2并存入线性表,然而线性表会变成[[1, 2], [1, 2]]而不是[[1], [1, 2]]。

当然实现了List接口的ArrayList和LinkedList类实现了clone函数,但是我们可以new一个list,初始化值是list类型

res.add(new LinkedList<>(res.get(j)));

这道题我们也可用DFS+回溯法来做,原理同77. combinations

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        int n = nums.length;
        List<List<Integer>> res = new ArrayList<>();
        if (n == 0) return res;
        Arrays.sort(nums);
        List<Integer> tmp = new ArrayList<>();
        dfs(res, tmp, nums, 0);
        return res;
    }
    public void dfs(List<List<Integer>> res, List<Integer> tmp, int[] nums, int start) {
        res.add(new ArrayList<>(tmp));
        if (tmp.size() == nums.length) return;
        for (int i = start; i < nums.length; ++i) {
            tmp.add(nums[i]);
            dfs(res, tmp, nums, i + 1);
            tmp.remove(tmp.size() - 1);
        }
    }
}

看大佬还有两种做法,分别是二叉树和列表,有兴趣可以点击参考资料去了解下。


参考资料: