18.组合(medium)

1.题目链接:

77. 组合 - 力扣(LeetCode)77. 组合 - 给定两个整数 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 <= n <= 20 * 1 <= k <= nhttps://leetcode.cn/problems/combinations/

2.题目描述:

给定两个整数 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 <= n <= 20​
     1 <= k <= n​
3. 解法(回溯):
算法思路:
题目要求我们从 1 到 n 中选择 k 个数的所有组合,其中不考虑顺序。也就是说,[1,2] 和 [2,1] 等价。我们需要找出所有的组合,但不能重复计算相同元素的不同顺序的组合。对于选择组合,我们需要进行如下流程:
1. 所有元素分别作为首位元素进行处理;
2. 在之后的位置上同理,选择所有元素分别作为当前位置元素进行处理;
3. 为避免计算重复组合,规定选择之后位置的元素时必须比前一个元素大,这样就不会有重复的组合([1,2] 和 [2,1] 中 [2,1] 不会出现)。​

递归函数设计:void dfs(vector<vector<int>>& ans, vector<int>& v, int step, int &n, int &k)​参数:step(当前需要进行处理的位置);​

返回值:无;
函数作用:某个元素作为首位元素出现时,查找所有可能的组合。

具体实现方法如下:
1. 定义一个二维数组和一维数组。二维数组用来记录所有组合,一维数组用来记录当前状态下的组   合。

2. 遍历 1 到 n-k+1,以当前数作为组合的首位元素进行递归(从 n-k+1 到 n 作为首位元素时,组合中一定不会存在 k 个元素)。

3. 递归函数的参数为两个数组、当前步骤以及 n 和 k。递归流程如下:​
        a. 结束条件:当前组合中已经有 k 个元素,将当前组合存进二维数组并返回。

         剪枝:如果当前位置之后的所有元素放入组合也不能满足组合中存在 k 个元素,直接返回。
        b. 从当前位置的下一个元素开始遍历到 n,将元素赋值到当前位置,递归下一个位置。​

Java算法代码:

class Solution {
    List<Integer> path;
    List<List<Integer>> ret;
    int n,k;
    public List<List<Integer>> combine(int _n, int _k) {
        n = _n; k = _k;
        path = new ArrayList<>();
        ret = new ArrayList<>();

        dfs(1);
        return ret;
    }
    public void dfs(int start){
        if(path.size() == k) {
            ret.add(new ArrayList<>(path));
            return ;
        }
        for (int i = start; i<= n; i++){
            path.add(i);
            dfs(i + 1);
            path.remove(path.size() - 1);
        }
    }
}

运行结果:

递归展开:

逻辑展开:

上面的一些细节,重点开递归展开一层后,后面的可以直接写出来(经过前面的题目的练习,应该已经可以做到了)。注意我的红字,是一个小细节。

---------------------------------------------------------------------------------------------------------------------------------

记住,相信你的递归函数,它可以做到!

记住,不理解时候,去尝试手动展开!

记住,逻辑展开(你不可能对所有的题目都进行手动展开)!

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值