[LeetCode 中等 二叉树 Deque]77.组合

题目描述

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

示例:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combinations
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

构建二叉树+DFS

public class Solution {
    
    public List<List<Integer>> combine(int n, int k) {
        List<List<Integer>> results = new ArrayList<>();
        // 排除特殊情况
        if (k <= 0 || n < k) {
            return results;
        }
        // 用来存储每一个生成的数
        Deque<Integer> number = new ArrayDeque<>();
        dfs(n, k, 1, results, number);
        return results;
    }

    private void dfs(int n, int k, int begin,  List<List<Integer>> results, Deque<Integer> number) {
        // 递归终止条件:长度到达k
        if(number.size() == k) {
            results.add(new ArrayList<>(number));
            return;
        }

        //因为题目不要求顺序[1,2] 和[2,1]是一样的  
        for(int i = begin; i < n+1; i++){
            number.addLast(i);
            //递归添加后面的数字,一直到长度是k为止
            dfs(n, k, i+1, results, number);
            // 比如产生[1,2][1,3][1,4]的情况下 1是公用的 但是2,3,4在其他递归中需要移除
            number.removeLast();
            }
    }
}

构建二叉树+DFS+剪枝优化

public class Solution {
    
    public List<List<Integer>> combine(int n, int k) {
        List<List<Integer>> results = new ArrayList<>();
        // 排除特殊情况
        if (k <= 0 || n < k) {
            return results;
        }
        // 用来存储每一个生成的数
        Deque<Integer> number = new ArrayDeque<>();
        dfs(n, k, 1, results, number);
        return results;
    }

    private void dfs(int n, int k, int begin,  List<List<Integer>> results, Deque<Integer> number) {
        // 递归终止条件:长度到达k
        if(number.size() == k) {
            results.add(new ArrayList<>(number));
            return;
        }

        //因为题目不要求顺序[1,2] 和[2,1]是一样的  
        for(int i = begin; i < n -(k-number.size())+2; i++){
            number.addLast(i);
            //递归添加后面的数字,一直到长度是k为止
            dfs(n, k, i+1, results, number);
            // 比如产生[1,2][1,3][1,4]的情况下 1是公用的 但是2,3,4在其他递归中需要移除
            number.removeLast();
            }
    }
}

构建二叉树+DFS+剪枝优化(另一种思路)

跟之前不一样的是 递归的标志变成了是不是选这个数

public class Solution {

    public List<List<Integer>> combine(int n, int k) {
        List<List<Integer>> res = new ArrayList<>();
        if (k <= 0 || n < k) {
            return res;
        }

        // 为了防止底层动态数组扩容,初始化的时候传入最大长度
        Deque<Integer> path = new ArrayDeque<>(k);
        dfs(1, n, k, path, res);
        return res;
    }

    private void dfs(int begin, int n, int k, Deque<Integer> path, List<List<Integer>> res) {
        if (k == 0) {
            res.add(new ArrayList<>(path));
            return;
        }

        // 基础版本的递归终止条件:if (begin == n + 1) {
        if (begin > n - k + 1) {
            return;
        }
        // 不选当前考虑的数 begin,直接递归到下一层
        dfs(begin + 1, n, k, path, res);

        // 不选当前考虑的数 begin,递归到下一层的时候 k - 1,这里 k 表示还需要选多少个数
        path.addLast(begin);
        dfs(begin + 1, n, k - 1, path, res);
        // 深度优先遍历有回头的过程,因此需要撤销选择
        path.removeLast();
    }
}

迭代

public class Solution {
    // 例如n=4,k=2 思路是从1开始[[1,2],[1,3],[1,4],[1,5] 
    // 发现越界变成[2,3],[2,4],[2,5]
    // 越界调整为[3,4]
    public List<List<Integer>> combine(int n, int k) {
        List<List<Integer>> ans = new ArrayList<>();
        List<Integer> number = new ArrayList<>();
        // 给temp初始化k个0(占位)
        for(int i = 0;i<k;i++){
            number.add(0);
        }


        // 0到k-1 对第i位进行叠加处理
        // -1代表结束迭代的循环
        int i = 0;
        while (i >= 0) {
            number.set(i, number.get(i)+ 1); 
            //当前数字大于 n,回到上一位数字 让他继续增大1
            if (number.get(i) > n) {
                i--;
            // 最后一位也已经被赋值了
            } else if (i == k - 1) { 
                ans.add(new ArrayList<>(number));
            //开始更新i位后面一位的数字
            }else {
                i++;
                //让后一位的值等于现在第i位的值
                number.set(i, number.get(i-1));
            }
        }
        return ans;
    }
}

动态规划

https://blog.csdn.net/wind_liang/article/details/104472769?utm_medium=distribute.pc_relevant_t0.none-task-blog-OPENSEARCH-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-OPENSEARCH-1.nonecase
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值