力扣第七十七题-组合

258 阅读2分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

前言

力扣第七十七题 组合 如下所示:

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

你可以按 任何顺序 返回答案。

示例 1:

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

示例 2:

输入: n = 1, k = 1
输出: [[1]]

一、思路

这一题是生成所有可能性的组合,那当然是使用递归来做了。

大致的步骤如下所示:

  1. 因为区间是 [1, n],所以从 1 开始
  2. 如果当前层结果的大小为 k 则将当前结果加入结果集

举个例子

此处以示例中的 n = 4, k = 2 作为例子

  1. 先选择 1 可以得到的结果有 [1, 2], [1, 3][1, 4]
  2. 再选择 2 可以得到的结果有 [2, 3], [2, 4]
  3. 再选择 3 可以得到 [3, 4]
  4. 最终将得到的结果集返回即可

值得注意的有如下两点:

  1. 每次当前层递归结束后,应将当前层添加的元素删除
  2. 应适当的剪枝:当临时一组结果的长度和还剩余的元素个数加起来都没有 k 大的话,应该终止当前层的递归。(例如:当 n = 4, k = 3 时,在递归的过程中,某一组的第一个元素选择 3 时,就应立即停止向下递归了。因为后面只有一个元素了,即使都选择了都无法构成正确的结果。)

二、实现

实现代码

实现代码与思路中保持一致,使用的时 List<Integer> 来存储某一组的结果

    List<Integer> temp = new ArrayList<>();
    List<List<Integer>> ans = new ArrayList<>();

    public List<List<Integer>> combine(int n, int k) {
        dfs(1, n, k);
        return ans;
    }

    public void dfs(int cur, int n, int k) {
        // 剪枝
        if (temp.size() + (n - cur + 1) < k) {
            return;
        }
        // 记录结果
        if (temp.size() == k) {
            ans.add(new ArrayList<>(temp));
            return;
        }
        temp.add(cur);
        dfs(cur + 1, n, k);
        temp.remove(temp.size() - 1);
        dfs(cur + 1, n, k);
    }

测试代码

    public static void main(String[] args) {
        new Number77().combine(4, 3);
    }

结果

image.png

三、总结

我后面又看到力扣上面还可以使用 字典序法 来解决此问题,这个方法还是比较难理解的,有兴趣的可以自行去力扣官方题解看一下!

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~