Day 23 - Leetcode 39组合总和 | Leetcode 40组合总和II | Leetcode 131分割回文串

文章目录

  • leetcode 39
  • leetcode 40
  • leetcode 131

leetcode 39

题目链接
Input: candidates = [2,3,6,7], target = 7
Output: [[2,2,3],[7]]

思路

  • 基本跟leetcode216, leetcode77 2道组合的题目相似
  • 注意元素可以重复,所以每次递归的时候index需要注意
class Solution {
    List<List<Integer>> res = new ArrayList<List<Integer>>();
    LinkedList<Integer> p = new LinkedList<>();
    int sum = 0;
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        if (candidates.length == 0)
            return res;
        backtracking(candidates, target, 0);
        return res;
    }
    public void backtracking(int[] candidates, int target, int index) {
        if (sum >= target) {
            if (sum == target)
                res.add(new ArrayList<>(p));
            return;
        }
        
        for (int i = index; i < candidates.length; ++i) {
            sum += candidates[i];
            p.add(candidates[i]);
            backtracking(candidates, target, i);
            sum -= candidates[i];
            p.removeLast();
        }
    }
}

leetcode 40

题目链接
是一个类似去重的题目,数组中有重复元素,但每个元素只能取1次,要求sum == target

思路

  • like [1, 1, 2], target = 3, output = [1, 2],只有1个唯一答案
  • 最简单想法,把答案放入set中,从而避免重复元素;——容易超时
  • 在回溯的过程中去重——树层去重
    • 首先要将数组排序,保证重复元素是相邻的
    • 树往下深度遍历的时候,可以取相同的元素
    • 树每一层不能取相同元素, ∵ \because 后面取的相同元素所得到的组合,一定在前面有过了
    • 定义used[]数组,可以用于在for循环中判断,当前是树枝(深度)搜索还是树层(广度)搜索
Day 23 - Leetcode 39组合总和 | Leetcode 40组合总和II | Leetcode 131分割回文串_第1张图片
class Solution {
    List<List<Integer>> res = new ArrayList<List<Integer>>();
    LinkedList<Integer> path = new LinkedList<>();
    int sum = 0;
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        if (candidates.length == 0)
            return null;
        boolean[] flag = new boolean[candidates.length];
        Arrays.sort(candidates);    //排序
        backtracking(candidates, target, 0, flag);
        return res;
    }
    public void backtracking(int[] candidates, int target, int index, boolean[] flag) {
        if (sum >= target) {
            if (sum == target)
                res.add(new ArrayList<>(path));
            return;
        }

        for (int i = index; i < candidates.length; ++i) {
            if (i != 0 && candidates[i] == candidates[i - 1] && !flag[i - 1])
                continue;
            sum += candidates[i];
            path.add(candidates[i]);
            flag[i] = true;
            backtracking(candidates, target, i + 1, flag);
            sum -= candidates[i];
            flag[i] = false;
            path.removeLast();
        }
    }
}

leetcode 131

题目链接
分割回文串 (palindrome)

思路

  • 有点类似组合问题,在选取一个a之后,在剩余的bcdef中去选取/切割第二段
Day 23 - Leetcode 39组合总和 | Leetcode 40组合总和II | Leetcode 131分割回文串_第2张图片
  • 判断子串substring [startIndex, i]是否是回文的
    • 双指针
class Solution {
    List<List<String>> res = new ArrayList<List<String>>();
    LinkedList<String> path = new LinkedList<>();
    public List<List<String>> partition(String s) {
        if (s.length() == 0)
            return null;
        backtreacking(s, 0);
        return res;
    }
    private void backtreacking(String s, int index) {
        if (index >= s.length()) {
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = index; i < s.length(); ++i) {
            if (isPalindrome(s, index, i)) {
                String t = s.substring(index, i + 1);   //substring取[i, j)
                path.add(t);
            }
            else 
                continue;
            backtreacking(s, i + 1);
            path.removeLast();
        }
    }
    private boolean isPalindrome(String s, int begin, int end) {
        int p = begin, q = end;
        while (p < q) {
            if (s.charAt(p++) != s.charAt(q--))
                return false;
        }
        return true;
    }
}

你可能感兴趣的:(Leetcode,leetcode,算法,java)