代码随想录算法训练营 Day25|回溯算法2

216.组合总和III

思路

按照回溯算法的逻辑,写代码。
递归函数的参数,除了原有的n, k, startIndex,增加一个sum,计算当前path中的和。
终止条件用sum与n比较,如果满足相等,且满足长度为k,则加入result。

尝试写代码:

class Solution:
    def __init__(self):
        self.path = []
        self.result = []

    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        self.backtracking(k, n, 1, 0)
        return self.result
        

    def backtracking(self, k, n, startIndex, sum):
        if sum == n:
            if len(self.path) == k:
                self.result.append(self.path[:])
                sum = 0
            return
        elif sum > n:
            return
        
        for i in range(startIndex, 10):
            if sum < n:
                self.path.append(i)
                sum += i
            self.backtracking(k, n, i + 1, sum)
            self.path.pop()
            sum -= i

成功通过!
但是对于终止条件那里还是有点模糊,不知道为什么两个if要嵌套着,不能and连接。
糊里糊涂的过了

根据代码随想录
终止条件,先判断path长度是否为k,如果不满足,返回;在此条件下,再判断当前的sum是否等于n。

剪枝1:
放在终止条件:如果当前sum比n大,则直接返回
剪枝2:
要求共有k个数,如果后面要取的数不够了,剪枝。
该剪枝放在for循环的条件里,写为9 - (k - path.size) + 1

最终代码

class Solution:
    def __init__(self):
        self.path = []
        self.result = []

    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        self.backtracking(k, n, 1, 0)
        return self.result

    def backtracking(self, k, n, startIndex, sum):
        if sum > n:
            return
        if len(self.path) == k:
            if sum == n:
                self.result.append(self.path[:])
            return
        for i in range(startIndex, 9 - (k - len(self.path)) + 2):
            self.path.append(i)
            sum += i
            self.backtracking(k, n, i + 1, sum)
            self.path.pop()
            sum -= i

总结
终止条件最基本的是长度是否与题目要求的相等,在此基础上再去判断和是否相等。
这样就不需要在for循环内增加条件,因为只要path的长度到k,都会返回,只不过如果再满足sum=n的话,就将当前的path加入result。
如此的整体结构就会很清晰

17.电话号码的字母组合

思路

有点不知道怎么弄
这里每个数字中都能挑选自己的字母,因此不存在startIndex。
先按照流程,递归函数的终止条件,如果是之前的题,需要判断path的长度,
但是由于7和9中有四个数字,而其他有三个数字,这里的for循环的范围不知道该如何确定
for循环就直接从digits中取数
问题
不知道如何将数组和各自的字母联系起来,可以尝试用字典,但具体不确定怎么写

根据代码随想录
要点:

  1. 用数组做一个映射,将数组的下标与内容对应
  2. 用二叉树画图,抽象理解,树的深度取决于输入的数的个数
  3. 函数参数中有一个index,不同于之前的startIndex,index表示当前递归到了第几个数字。因为之前的题是在一个集合中组合,本题是在两个集合中组合,因此不需要startIndex确定集合中之前遍历过哪些元素
  4. 终止条件:用index判断是否遍历到了digits.size。然后收获结果,返回。这里不同于之前用path.size。不过我觉得用path.size也可以
  5. 取出一个数,通过数组映射得到这个数对应的字母
  6. for循环的范围通过上面得到的数字对应的字母的size决定
  7. 递归时,index + 1,使得下次递归时,取下一个数

尝试写代码:

class Solution:
    def __init__(self):
        self.path = ''
        self.result = []
        self.letterMap = [
            '',      # 0
            '',      # 1
            'abc',   # 2
            'def',   # 3
            'ghi',   # 4
            'jkl',   # 5
            'mno',   # 6
            'pqrs',  # 7
            'tuv',   # 8
            'wxyz'   # 9
        ]
    def letterCombinations(self, digits: str) -> List[str]:
        self.backtracking(digits, 0)
        return self.result

    def backtracking(self, digits, index):
        if len(self.path) == len(digits):
            self.result.append(self.path)
            return
        digit = int(digits[index])
        letter = self.letterMap[digit]
        for i in range(len(letter)):
            self.path += letter[i]
            self.backtracking(digits, index + 1)
            self.path = self.path[:-1]

有的通过,有的不对
如果给的digits为空,应该输出空列表,但是result有一个空引号

根据代码随想录:在给定函数开头加个if判断

最终代码

class Solution:
    def __init__(self):
        self.path = ''
        self.result = []
        self.letterMap = [
            '',      # 0
            '',      # 1
            'abc',   # 2
            'def',   # 3
            'ghi',   # 4
            'jkl',   # 5
            'mno',   # 6
            'pqrs',  # 7
            'tuv',   # 8
            'wxyz'   # 9
        ]
    def letterCombinations(self, digits: str) -> List[str]:
        if len(digits) == 0:
            return self.result
        self.backtracking(digits, 0)
        return self.result

    def backtracking(self, digits, index):
        if index == len(digits):
            self.result.append(self.path)
            return
        digit = int(digits[index])
        letter = self.letterMap[digit]
        for i in range(len(letter)):
            self.path += letter[i]
            self.backtracking(digits, index + 1)
            self.path = self.path[:-1]

Python方法

使用切片的方式来删除字符串的最后几个字符:
删除最后两个字符:s = s[:-2]
删除最后一个字符:s = s[:-1]
s[:-1]的意思就是s字符串取从第0个字符至倒数第一个字符的前一个字符,这样就达到了去掉最后一个字符的目的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值