算法刷题|216.组合总和|||、17.电话号码的字母组合

组合总和|||

题目:找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:

只使用数字1到9
每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

思路:先根据题目抽象成一个多叉树,然后按照要求收集结果即可
组合总和|||

class Solution {
    public List<List<Integer>> combinationSum3(int k, int n) {
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> path = new ArrayList<>();
        backtracking(k,n,0,1,path,res);
        return res;
    }
    private void backtracking(int k,int n,int sum,int startIndex,List<Integer> path,List<List<Integer>> res){
        if(path.size() == k){// 终止条件 当收集的路径大小等于k的时候就可以返回了
            if(n == sum){
                res.add(new ArrayList<>(path));
            }
        }
        for(int i = startIndex;i<=9;i++){// 每一层从startIndex遍历开始收集路径
            sum+=i;// 累加和
            path.add(i);// 收集这一层的元素
            backtracking(k,n,sum,i+1,path,res);
            // 回溯
            sum-=i;
            path.remove(path.size()-1);
        }
    }
}

剪枝

class Solution {
    public List<List<Integer>> combinationSum3(int k, int n) {
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> path = new ArrayList<>();
        backtracking(k,n,0,1,path,res);
        return res;
    }
    private void backtracking(int k,int n,int sum,int startIndex,List<Integer> path,List<List<Integer>> res){
        // 剪枝
        if(sum > n){
            return;
        }
        if(path.size() == k){// 终止条件 当收集的路径大小等于k的时候就可以返回了
            if(n == sum){
                res.add(new ArrayList<>(path));
            }
        }
        // 剪枝
        // 已经收集了path.size()个元素,还需要收集k-path.size()
        // 例如 k=5,path.size() = 2,还需要收集3个元素,那么下面的循环的i从8开始就没有意义了,因为即使从8开始,后面最多也就收集到2个元素了(8,9),不够3个了,所有i要<7
        int lastIndex = 9 - (k-path.size()) + 1;
        for(int i = startIndex;i<=lastIndex;i++){// 每一层从startIndex遍历开始收集路径
            sum+=i;// 累加和
            path.add(i);// 收集这一层的元素
            backtracking(k,n,sum,i+1,path,res);
            // 回溯
            sum-=i;
            path.remove(path.size()-1);
        }
    }
}

电话号码的字母组合

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

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

思路:先抽象成多叉树,然后寻找终止条件,已经回溯的点
电话号码的字母组合

class Solution {
    public List<String> letterCombinations(String digits) {
        List<String> res = new ArrayList<>();
        if(digits == null || digits.length() == 0){
            return res;
        }
        String[] strArr = new String[]{"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
        StringBuilder path = new StringBuilder(); 
        backtracking(digits,0,path,res,strArr);
        return res;
    }
    // index表示递归到digits的那个数字了
    private void backtracking(String digits,int index,StringBuilder path,List<String> res,String[] strArr){
        if(index == digits.length()){
            res.add(path.toString());
            return;
        }
        // 单层递归
        String s = strArr[digits.charAt(index) - '0'];
        for(int i = 0;i<s.length();i++){
            // 收集当前层数据
            path.append(s.charAt(i));
            backtracking(digits,index + 1,path,res,strArr);
            // 回溯
            path.deleteCharAt(path.length() - 1);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值