【Leetcode & 剑指offer刷题】回溯算法-排列组合77&216

这篇博客对比分析了LeetCode的两道组合问题,77题要求在1到n中找到k个数的所有组合,而216题则限制了数字范围为[1,2,3,4,5,6,7,8,9]且求和为n的k个数组合。两题都使用回溯法解决,但剪枝策略有所不同。77题代码中,回溯函数直接从1开始,而216题需考虑当前和与目标和的关系。
摘要由CSDN通过智能技术生成

leetcode.77.组合

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

示例

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

leetcode.216.组合总和 III

题目链接
找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。

说明:
所有数字都是正整数。
解集不能包含重复的组合。

示例

example1

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

example2

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

两题差异

  1. 题一是在1至n中选取k个数的组合
  2. 题二是在[1,2,3,4,5,6,7,8,9]这个集合中找到sum为n的k个数的组合,集合已经固定
  3. 两题的返回都不允许重复

77题代码

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    Deque<Integer> path = new ArrayDeque<>();

    public List<List<Integer>> combine(int n, int k) {
        if (k <= 0 || n < k){
            return res;
        }
        
        //因为是1...n,所以index从1开始
        backtracking(n, k, 1);
        return res;
    }

    private void backtracking(int n, int k, int startIndex){
        if (path.size() == k){
            res.add(new ArrayList<>(path));
            return;
        }

		//需要注意下方剪枝部分i <= n - (k - path.size()) + 1
        for (int i = startIndex; i <= n - (k - path.size()) + 1 ; i++){
            path.addLast(i);
            backtracking(n, k, i + 1);
            path.removeLast();
        }
    }
}

216题代码

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    Deque<Integer> path = new ArrayDeque<>();

    public List<List<Integer>> combinationSum3(int k, int n) {
        backtracking(k, n, 0, 1);
        return res;
    }
    
	//相比于77题,backtracking函数体的参数增加了sum和target;target相当于题目给的n,sum是当前的和
    private void backtracking(int k, int target, int sum, int startIndex){
    	//相比77,增加sum的判断
        if (path.size() == k && sum == target){
            res.add(new ArrayList<>(path));
            return;
        }

		//相比77,剪枝部分有差异,同时i最大为9,不为n
        for (int i = startIndex; i <= 9 && sum+i <=target ; i++){
            sum += i;
            path.addLast(i);
            backtracking(k, target, sum, i + 1);
            sum -= i;
            path.removeLast();

        }
    }
}

参考

参考了Carl大佬c++版的77题216题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值