Leetcoder Day22| 回溯part02:组合总和+字母组合

语言:Java/Go

216.组合总和III

找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。

说明:

  • 所有数字都是正整数。
  • 解集不能包含重复的组合。

示例 1: 输入: k = 3, n = 7 输出: [[1,2,4]]

示例 2: 输入: k = 3, n = 9 输出: [[1,2,6], [1,3,5], [2,3,4]]

  本题和上一章组合题基本类似,就是这里限制了组合的范围为[1,9]所以相当于在循环中需要用9来限制循环次数。这里递归结束条件就是找到了和为n的k个数的组合,因此可以设置一个sum惨参数来计算当前的和。每次递归都要伴随着回溯,回溯就是把sum减去当前的元素,path去掉当前元素。剪枝操作在循环条件中和上一题是一致的,就是用9-(path.size())+1,这里还要注意一个隐藏条件,如果当前的sum已经大于要求的n,也可以停止循环了。记住在这个判断里依然要进行回溯。

class Solution {
    List<List<Integer>> res= new ArrayList<>();
    LinkedList<Integer> path = new LinkedList<>();
    public void backTracking(int k, int n, int sum, int startIdx){
        if(path.size()==k){
            if(n==sum){  //已有k个数且和为n
                res.add(new ArrayList<>(path));
            }
            return;
        }
        for(int i=startIdx;i<=9-(k-path.size())+1;i++){ //进行剪枝,如果sum大于n,结束递归
            sum+=i;
            path.add(i);
            if(sum>n){
                sum-=i;
                path.removeLast();
                return;
            }
            backTracking(k, n, sum, i+1);
            sum-=i;
            path.removeLast();
        }
    }
    public List<List<Integer>> combinationSum3(int k, int n) {
        backTracking(k,n,0,1);
        return res;
    }
}

17.电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例 1:

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

输入:digits = ""
输出:[]

示例 3:

输入:digits = "2"
输出:["a","b","c"]

本题看到的时候比较好奇,字母和数字之间的映射怎么巧妙处理,代码随想录里给出的方法是用map或者二维数组进行映射,2-9都有对应的祖母,0和1用空字符来替代,在java中表示如下:

String[] numString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

终止条件就是如果startIdx 等于 输入的数字个数(digits.size)了(本来index就是用来遍历digits的)。

class Solution {
    List<String> res = new ArrayList<>();
    //涉及大量的字符串拼接,所以这里选择更为高效的 StringBuild
    StringBuilder temp = new StringBuilder();
    String[] numString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

    public List<String> letterCombinations(String digits) {
        if(digits==null || digits.length()==0){
            return res;
        }
        backTracking(digits, 0);
        return res;
    }
    public void backTracking(String digits, int startIdx){
        if(startIdx==digits.length()){// 字符串长度length()
            res.add(temp.toString());  
            return;
        }
        //用str表示数字对应的字符串
        /*
        digits.charAt(startIdx)表示当前第startIdx个元素对应的数字,初始值为0
        如‘23’,startIdx=0,所以当前要取的是‘2’,这里是字符串
        digits.charAt(startIdx)-'0'表示‘2’与‘0’之间的差值。这样做的目的是将字符数字转换为对应的整数值。
        所以这里就变成了整数2
        numString(digits.charAt(startIdx)-'0')对应的就是2所对应的字母‘abc’
         */
        String str=numString[digits.charAt(startIdx)-'0']; 
        for(int i=0;i<str.length();i++){
            temp.append(str.charAt(i));
            backTracking(digits, startIdx+1);
            temp.deleteCharAt(temp.length()-1);
        }

    } 
    
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值