力扣labuladong一刷day65天回溯大集合

发布时间:2024年01月23日

力扣labuladong一刷day65天回溯大集合

一、17. 电话号码的字母组合

题目链接:https://leetcode.cn/problems/letter-combinations-of-a-phone-number/description/
思路:还是典型的组合问题,只不过每次递归需要替换for循环的集合。
组合类型的题为什么需要起始索引?是因为为了避免递归走回头路,出现2,3和3,2的问题,从组合角度上来看这两种就是一种,但是对于固定的单一集合来说确实是如此,需要起始索引,避免走回头路,而对于多集合来说,每个集合都不重复,没有走回头路这一说,故多集合不需要起始索引,本题即是。

class Solution {
    String[] strList = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    StringBuilder builder;
    List<String> list;
    public List<String> letterCombinations(String digits) {
        builder = new StringBuilder();
        list = new ArrayList<>();
        if(digits.length() == 0) return list;
        backTracking(digits, 0);
        return list;
    }
    void backTracking(String digits, int i) {
        if (i == digits.length()) {
            list.add(builder.toString());
            return;
        }
        String temp = strList[digits.charAt(i)-'0'];
        for (int k = 0; k < temp.length(); k++) {
            builder.append(temp.charAt(k));
            backTracking(digits, i+1);
            builder.deleteCharAt(builder.length()-1);
        }
    }
}

二、39. 组合总和

题目链接:https://leetcode.cn/problems/combination-sum/description/
思路:这个新类型,是无重复元素,可以复选,复选的话即是,单条递归链路,a元素可用,向下递归a还得可用,才能满足可复选,故起始索引为startIndex。如果题目是无重复元素,不可复选,起始索引为startIndex+1.

class Solution {
   List<List<Integer>> arrayLists;
    List<Integer> list;
    int sum = 0;
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        arrayLists = new ArrayList<>();
        list = new ArrayList<>();
        backTracking(candidates, target, 0);
        return arrayLists;
    }
    void backTracking(int[] candidates, int target, int index) {
        if (sum > target) return;
        if (sum == target) {
            arrayLists.add(new ArrayList<>(list));
            return;
        }
        for (int i = index; i < candidates.length; i++) {
            sum += candidates[i];
            list.add(candidates[i]);
            backTracking(candidates, target, i);
            sum -= candidates[i];
            list.remove(list.size()-1);
        }
    }
}

本题还可以提前剪枝一下,但是从结果上来看没有多大提升,提前预判结果是需要排序的,才能确保后续元素都更大。

List<List<Integer>> arrayLists;
    List<Integer> list;
    int sum = 0;
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        arrayLists = new ArrayList<>();
        list = new ArrayList<>();
        Arrays.sort(candidates);
        backTracking(candidates, target, 0);
        return arrayLists;
    }
    void backTracking(int[] candidates, int target, int index) {
        if (sum == target) {
            arrayLists.add(new ArrayList<>(list));
            return;
        }
        for (int i = index; i < candidates.length && sum+candidates[i] <= target; i++) {
            sum += candidates[i];
            list.add(candidates[i]);
            backTracking(candidates, target, i);
            sum -= candidates[i];
            list.remove(list.size()-1);
        }
    }
文章来源:https://blog.csdn.net/qq_43511039/article/details/135763688
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。