两道回溯法17_39

17. Letter Combinations of a Phone Number

给一串数字,获得按照手机键盘上对应的字母的所有组合。

Input: “23”
Output: [“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].

用回溯法:

HashMap<Integer, String> map = new HashMap<>();
public List<String> letterCombinations(String digits) {
    if (digits.length() < 1) return Collections.emptyList();

    map.put(2, "abc");
    map.put(3, "def");
    map.put(4, "ghi");
    map.put(5, "jkl");
    map.put(6, "mno");
    map.put(7, "pqrs");
    map.put(8, "tuv");
    map.put(9, "wxyz");
    help(digits, new StringBuffer(""), 0);
    return res;
}

List<String> res = new ArrayList<>();
public void help(String digits, StringBuffer str, int index) {
    if (digits.length() == str.length())
        res.add(str.toString());
    else {
    	//每次递归时获得当前数字对应的所以字母,并遍历它们
        String temp = map.get(digits.charAt(index) - '0');
        for (int i = 0; i < temp.length(); i++) {
            str.append(temp.charAt(i));
            help(digits, str, index+1);
            //在回溯时去掉刚才加入的字符
            str.deleteCharAt(str.length()-1);
        }
    }
}

39. Combination Sum

给一个没有重复数的数组,和一个target,求数组中能组合成target(每个数字可以重复使用)的组合个数。
Input: candidates = [2,3,6,7], target = 7,
A solution set is:
[ [7], [2,2,3] ]

也是回溯法,但和上面的区别是数组中每个元素可以重复使用,所以有细微区别:遍历时的指标index不随每次循环递增,而是当每次获得一个解时再增加:

public List<List<Integer>> combinationSum(int[] candidates, int target) {
    Arrays.sort(candidates);
    help(candidates, target, 0, 0, new ArrayList<>());

    return res;
}

List<List<Integer>> res = new ArrayList<>();
public void help(int[] candidates, int target, int index, int sum, List<Integer> nums) {
    if (sum == target) {
    	//不能直接将nums加入到res解列表中,因为nums也是一个列表,所以每次add到res中的列表指向的都是同一个对象。
    	//然后在程序执行中,它作为一个参数,其中的值是一直在变化的,在程序结束时nums会回归到空列表,那么添加进res的就都是空列表了。
        List<Integer> temp = new ArrayList<>(nums);
        res.add(temp);
    } else {
        for (; index < candidates.length; ) {
            if (sum + candidates[index] <= target) {
                nums.add(candidates[index]);
                help(candidates, target, index, sum + candidates[index], nums);
                //获得一个解后index加一
                nums.remove(nums.size()-1);
                index++;
            }else {
            	//因为数组已经有序,所以当遇到一个sum大于target的元素后,剩下的元素就都不用看了
                break;
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值