代码随想录算法训练营第二十五天|216.组合总和III、17.电话号码的字母组合

代码随想录算法训练营第二十五天|216.组合总和III、17.电话号码的字母组合

216.组合总和III

题目链接

问题简述:在1~9中找出个数为k的和为n的所有组合。

思考:和上一次的回溯很像很像。

算法思路:定义一个startIndex作为每次循环的起始位置,path为每个结果的路径,sum为当前路径的总和。进行操作时首先判断当前的sum是否大于n,如果大于n直接返回并回溯,然后判断当path元素个数为k且总和为n时,将path加入lists并返回。在path中加入元素,sum中加入当前元素,再进行递归,递归的startIndex加1即为加入当前元素后面的元素,保证path中不再重复。递归完成后再移除上一步加入的元素,并将sum剪去当前元素值。同时在进行for循环时考虑到剪枝,i最大只能为9 - (k - path.size()) + 1,当大于这个数时,结果不再成立。

import java.util.ArrayList;
import java.util.List;

class Solution {
    List<List<Integer>> lists = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    int sum = 0;
    public List<List<Integer>> combinationSum3(int k, int n) {
        backtracking(n, k, 1);
        return lists;
    }
    public void backtracking(int n,int k,int startIndex){
        //剪枝叶
        if (sum > n){
            return;
        }
        //确定终止条件
        if (path.size() == k && sum == n){
            //这里注意需要新创建一个ArrayList将path的值放入lists,不可以直接将path放入
            lists.add(new ArrayList<>(path));
            return;
        }
        //进行循环并回溯,同时进行剪枝
        for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) {
            path.add(i);
            sum += i;
            backtracking(n, k, i + 1);
          	//回溯
            sum -= i;
            path.remove(path.size() - 1);
        }
    }
}

17.电话号码的字母组合

题目链接

问题简述:将给定的digits中所有的数字对应的字母任取一个组合成长度为digits长度的字符串,将左右的结果返回。

思考:这个题涉及到的将字符转换为数字的方法需要注意,直接-'0'将字符数字变为数字。然后将数字对应成字母的方法也要记住,之前一直在想用某个函数对应一下数字和字母,其实是一个等差数列,但是因为有的数字对应了四个字母所以不行。

算法思路:定义一个startIndex作为每次递归中digits的位置,s存储每个结果,list存储s的集合。将所有的字母存入字符串数组numString。如果digits为空,返回空list;如果s的长度等于digits的长度,则将s加入list。如果不等于,则循环当前数字对应的字母个数次,每次将当前数字对应字母加入s,再进行递归下一个数字,最好删除当前字母进行回溯。

import java.util.ArrayList;
import java.util.List;

class Solution {
    //用来存最终结果
    List<String> list = new ArrayList<>();
    //用来存list中的每个字符串
    StringBuilder s = 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 list;
        }
        //最初的其实位置为0
        backtracking(digits, 0);
        return list;
    }

    public void backtracking(String digits, int startIndex){
        //如果长度够了,则加入进list
        if (s.length() == digits.length()){
            list.add(new String(s));
            return;
        }
        //循环的次数为当前字符对应字母的个数,-'0'将字符变为数字
        int length = numString[digits.charAt(startIndex) - '0'].length();
        for (int j = 0; j < length; j++) {
            //加入当前digits的i位置对应的字母
            s.append(numString[digits.charAt(startIndex) - '0'].charAt(j));
            //递归加入字母
            backtracking(digits,startIndex + 1);
            //进行回溯
            s.deleteCharAt(s.length() - 1);
        }
    }
}

感想

我感觉我心里就默认了旅游是对自己努力的奖励,看电视剧是自己浪费时间的证据。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值