Day24&25_Backtracking, Leetcode 77, 216, 17

文章通过三个LeetCode题目展示了回溯算法的应用,包括组合生成、数字组合成指定和以及电话号码字母组合。解题策略涉及递归、回溯过程中的变量管理和修剪无效路径。每个问题的核心是调整回溯条件以适应不同场景。
摘要由CSDN通过智能技术生成

Leetcode 77

- LeetCode

题目的第一想法:

这道题的要求是穷尽一些数字的组合,需要注意的是数字的位置并不重要,因此,(1,2)和(2,1)算是同一个项。这道题应该算是回溯的模板了。基本上需要注意的是回溯需要的一些variable。比如开始的数值,在recurrsion里面使用的for循环都算是所谓的回溯法“公式”中的一环。还有必要是的一些trim的操作。另外,leetcode上的提供的最快写法实际上是可以只使用recursion来写的。

class Solution {
    List<List<Integer>> rlist = new LinkedList<>();
    public List<List<Integer>> combine(int n, int k) {
        List<List<Integer>> rlist = new LinkedList<>();
        List<Integer> tempList = new LinkedList<>();
        combine(1, n, k, tempList, rlist);
        return rlist;
    }

     public void combine(int start, int n, int k, List<Integer> temp, List<List<Integer>> rlist){
         if(temp.size() == k){
             rlist.add(new LinkedList<>(temp));
             return;
         }else{
             for(int i = start; i <= n - (k - temp.size()) + 1; i++){
                 temp.add(i);
                 combine(i + 1, n, k, temp, rlist);
                 temp.remove(temp.size() - 1);
             }
         }
     }
}

看完代码随想录之后的想法:

这里修剪的逻辑是,在某一个回溯的某一个时刻。会出现哪怕穷尽接下来所有的组合,也无法满足结果放入返回的表里面的情况。此时,我们可以把这些无用的操作通过条件的判断来裁剪掉。

Leetcode 216

- LeetCode

题目的第一想法:

这道题的要求是在一些数字中找到k个数字相加=n。其中k和n是以知的。这道题和上一道题的区别是停止条件的不同。因为我们需要找到相加=n的组合。所以还需要一个sum。在每次移除或添加数字时也要对sum进行相应的操作(+= || -=)。其余的和77题一样。

class Solution {
    public List<List<Integer>> combinationSum3(int k, int n) {
        List<Integer> list = new LinkedList<>();
        List<List<Integer>> rlist = new LinkedList<>();
        backTracking(k, n, 1, list, rlist, 0);
        return rlist;
    }

    public void backTracking(int k, int n, int start, List<Integer> list, List<List<Integer>> rlist, int sum){
        if(list.size() == k && sum == n){
            rlist.add(new LinkedList<>(list));
            return;
        }
        for(int i = start; i <= 9; i++){
            if(i > n) return;
            else if(k - list.size() >= 9 - i + 2) return;
            list.add(i);
            sum += i;
            backTracking(k, n, i + 1, list, rlist, sum);
            sum -= i;
            list.remove(list.size() - 1);
        }
    }
}

看完代码随想录之后的想法:

记得trim

Leetcode 17

- LeetCode

题目的第一想法:

这道题的要求给出几个九宫格上的数字。找到这几个数字这道题我的第一想法是使用两个for loop,一个用来遍历当前的数字,另一个则用来遍历每个数字的字母。但直接使用两个for loop的问题是,第二个数字内的字母会和自己重复。原因在于在最初的loop中,我并没能找到一个合理的条件来只停止最初的for loop。因为所有的递归都使用同样的结构。所以很难只停止其中的某一个for loop。

class Solution {
    HashMap<Character, String> match = new HashMap<>(){{
        put('0', "");
        put('2', "abc");
        put('3', "def");
        put('4', "ghi");
        put('5', "jkl");
        put('6', "mno");
        put('7', "pqrs");
        put('8', "tuv");
        put('9', "wxyz");
        put('1', "");
    }

    };
    public List<String> letterCombinations(String digits) {
        List<String> rlist = new LinkedList<>();
        StringBuilder st = new StringBuilder();
        StringBuilder dd = new StringBuilder(digits);
        if(digits.isEmpty()) return rlist;
        backTracking(0, st, dd, rlist);
        return rlist;
    }

    public void backTracking(int start, StringBuilder st, StringBuilder digits, List<String> rlist){
        if(start == digits.length()){
            rlist.add(st.toString());
            return;
        }
        for(int j = 0; j < match.get(digits.charAt(start)).length(); j++){
            st.append(match.get(digits.charAt(start)).charAt(j));
            backTracking(start + 1, st, digits, rlist);
            st.deleteCharAt(st.length() - 1);
        }
    }
}

看完代码随想录之后的想法:

这个逻辑还是很酷的。使用一个递归来传递字母,for loop来传递组合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值