LeetCode-77.组合(相关话题:回溯算法)

给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。

示例:

输入: n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

解题思路:深度优先+回溯算法

java代码:

class Solution {
    public List> combine(int n, int k) {
        List> res = new LinkedList<>();
        boolean[] f = new boolean[n];
        List tmp = new ArrayList<>(k);

        dfs(k, 0, n, f, tmp, res);

        return res;
    }
    private void dfs(int left, int s, int n, boolean[] f, List tmp, List> res) {
        if(0 == left) {
            res.add(tmp);
            return;
        }

        for(int i = s; i < n; i++) {
            if(f[i])
                continue;

            f[i] = true;
            List t = new ArrayList<>(tmp);
            t.add(i+1);
            dfs(left-1, i+1, n, f, t, res);

            f[i] = false;
        }
    }
}

注:由于List是指针传递,所以每次深度搜索的时候,都需要将存放结果子集的list(即tmp)复制一份出来,但是这样效率很低,上述代码的运行时间在150+ms。

对上述代码进行优化,每次深度搜索的时候不再copy一份存放结果子集的list(即tmp),而是当判断tmp为某一个结果子集的时候,再copy一份tmp存放到结果集中,代码如下:

class Solution {
    public List> combine(int n, int k) {
        List> res = new LinkedList<>();
        boolean[] f = new boolean[n];
        List tmp = new ArrayList<>(k);

        dfs(k, 0, n, f, tmp, res);

        return res;
    }
    private void dfs(int left, int s, int n, boolean[] f, List tmp, List> res) {
        if(0 == left) {
            res.add(new ArrayList<>(tmp));
            return;
        }

        for(int i = s; i < n; i++) {
            if(f[i])
                continue;

            f[i] = true;
            tmp.add(i+1);
            dfs(left-1, i+1, n, f, tmp, res);

            f[i] = false;
            tmp.remove(tmp.size()-1);
        }
    }
}

运行时间在25ms左右

你可能感兴趣的:(LeetCode,Java)