代码随想录算法训练营Day27|LC39 组合总和&LC40 组合总和II&LC131 分割回文串

文章介绍了如何使用回溯算法解决组合总和问题,包括基本版本、去重版本以及涉及字符串操作的分割回文串问题,强调了递归逻辑和特殊条件的处理。
摘要由CSDN通过智能技术生成

一句话总结:菜就多练。

原题链接:39 组合总和

还是基础的回溯算法的模板,主要需要注意的是回溯递归过程的逻辑。

class Solution {
    List<List<Integer>> ans = new ArrayList<>();
    List<Integer> path = new ArrayList<>();

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);
        backtrack(candidates, target, 0);
        return ans;
    }

    private void backtrack(int[] candidates, int target, int start) {
        if (target == 0) {
            ans.add(new ArrayList<>(path));
            return;
        }
        for (int i = start; i < candidates.length; ++i) {
            if (target - candidates[i] < 0) break;
            path.add(candidates[i]);
            backtrack(candidates, target - candidates[i], i);
            path.removeLast();
        }
    }
}

 原题链接:40 组合总和II

与上一题组合总和类似,但多了一条每个数字在每个组合里仅能使用一次的限制。因此单层回溯的逻辑需要加上一条判断,以实现去重操作。

class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> ans = new ArrayList<>();
        List<Integer> path = new ArrayList<>();     
        Arrays.sort(candidates);
        backtrack(candidates, target, 0, ans, path);
        return ans;
    }

    private void backtrack(int[] candidates, int target, int start, List<List<Integer>> ans, List<Integer> path) {
        if (target == 0) {
            ans.add(new ArrayList<>(path));
            return;
        }
        for (int i = start; i < candidates.length; ++i) {
            if (target - candidates[i] < 0) break;
            if (i > start && candidates[i] == candidates[i - 1]) continue;
            path.add(candidates[i]);
            backtrack(candidates, target - candidates[i], i + 1, ans, path);
            path.removeLast();
        }
    }
}

 原题链接:131 分割回文串

相较于前两题,此题涉及到字符串的操作,更加复杂一些,除了常规的回溯及其单层递归逻辑以外还需要判断是否回文串。

class Solution {
    List<List<String>> ans = new ArrayList<>();
    List<String> sub = new ArrayList<>();
    String s;

    public List<List<String>> partition(String s) {
        this.s = s;
        backtrack(0, 0);
        return ans;
    }

    private void backtrack(int i, int start) {
        if (i == s.length()) {
            ans.add(new ArrayList<>(sub));
            return;
        }
        if (i < s.length() - 1) backtrack(i + 1, start);
        String t = s.substring(start, i + 1);
        if (check(t)) {
            sub.add(t);
            backtrack(i + 1, i + 1);
            sub.removeLast();
        }
    }

    private boolean check(String s) {
        return s.equals(new StringBuffer(s).reverse().toString());
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值