Day23 39. 组合总和 | 40. 组合总和 II | 131. 分割回文串

53 阅读2分钟

39. 组合总和 - 力扣(LeetCode)

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> ans = new ArrayList<>();
        List<Integer> path = new ArrayList<>();
        dfs(0, target, candidates, ans, path);
        return ans;
    }

    public void dfs(int i, int left, int[] candidates, List<List<Integer>> ans, List<Integer> path) {
        if (left == 0) {
            // 找到了一个组合
            ans.add(new ArrayList<>(path));
            return;
        }
        if (i == candidates.length || left < 0) {
            return;
        }
        // 不选
        dfs(i + 1, left, candidates, ans, path);
        // 选
        path.add(candidates[i]);
        dfs(i, left - candidates[i], candidates, ans, path);
        path.remove(path.size() - 1);// 恢复现场
    }

}

40. 组合总和 II - 力扣(LeetCode)

public class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> ans = new ArrayList<>();
        Arrays.sort(candidates); // 排序以去除重复组合
        List<Integer> path = new ArrayList<>();
        dfs(0, target, path, candidates, ans);
        return ans;
    }

    private void dfs(int start, int left, List<Integer> path, int[] candidates, List<List<Integer>> ans) {
        if (left == 0) {
            ans.add(new ArrayList<>(path));
            return;
        }
        if (left < 0 || start == candidates.length) {
            return;
        }

        for (int i = start; i < candidates.length; i++) {
            // 如果当前元素与前一个元素相同,则跳过,避免重复组合
            if (i > start && candidates[i] == candidates[i - 1]) {
                continue;
            }
            // 选当前元素
            path.add(candidates[i]);
            dfs(i + 1, left - candidates[i], path, candidates, ans); // 继续从下一个元素开始
            path.remove(path.size() - 1); // 回溯
        }
    }
}

131. 分割回文串 - 力扣(LeetCode)

class Solution {

    // 用于存储所有可能的回文子串分割方案
    private final List<List<String>> ans = new ArrayList<>();
    // 用于存储当前构建的回文子串分割方案
    private final List<String> path = new ArrayList<>();
    // 输入字符串
    private String s;

    /**
     * 分割给定字符串的所有可能的回文子串分割方案。
     * 
     * @param s 输入字符串
     * @return 所有可能的回文子串分割方案
     */
    public List<List<String>> partition(String s) {
        this.s = s; // 设置输入字符串
        dfs(0); // 从第一个字符开始搜索
        return ans; // 返回所有可能的分割方案
    }

    /**
     * 深度优先搜索方法,用于查找所有可能的回文子串分割方案。
     * 
     * @param start 当前搜索的起始位置
     */
    private void dfs(int start) {
        if (start == s.length()) {
            // 如果搜索到了字符串的末尾,添加当前路径到结果集中
            ans.add(new ArrayList<>(path));
            return;
        }

        // 遍历从当前位置到字符串末尾的所有可能的终点
        for (int end = start; end < s.length(); end++) {
            // 如果从 start 到 end 的子串是回文串
            if (isPalindrome(start, end)) {
                // 将回文子串添加到当前路径中
                path.add(s.substring(start, end + 1));
                // 递归搜索下一个可能的分割点
                dfs(end + 1);
                // 回溯:移除最后一个添加的子串
                path.remove(path.size() - 1);
            }
        }
    }

    /**
     * 检查给定范围内的子串是否为回文串。
     * 
     * @param left  子串的左边界
     * @param right 子串的右边界
     * @return 如果子串是回文串则返回 true,否则返回 false
     */
    private boolean isPalindrome(int left, int right) {
        while (left < right) {
            // 如果左右两端的字符不相等,则不是回文串
            if (s.charAt(left++) != s.charAt(right--)) {
                return false;
            }
        }
        // 如果所有对应字符都相等,则是回文串
        return true;
    }
}