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

216.组合总和III

题目描述: 216.组合总和III.

解法

回溯
class Solution(object):
    def backtrack(self,k,start,path,last):
        if len(path) == k and last == 0:
            self.res.append(path[:])
            return
        elif len(path) == k or last == 0:
            return
        
        for i in range(start,10-(k-len(path)-1)):
            path.append(i)
            self.backtrack(k,i+1,path,last-i)
            path.pop()
    
    def combinationSum3(self, k, n):
        self.res = []
        self.backtrack(k,1,[],n)
        return self.res

终止条件是总长并且总和正确
剪枝的部分有两个:一是总长和总和只有一个符合条件,就可以退出。二是遍历的长度问题,总共最多遍历到9,那么右边界基准就是10,已经遍历了len(path)个,共需要k个,那么还需要遍历k-len(path)个,再去除当前遍历的内容,就还需要遍历k-len(path)-1个,所以右边界为10-(k-len(path)-1)
我这里使用了剩余需要的和,要求的总和减去现有的总和,这样就少了一个参数。

17.电话号码的字母组合

题目描述: 17.电话号码的字母组合.

解法

回溯
class Solution(object):
    def backtrack(self,floor,path,digits):
        if floor == len(digits):
            self.res.append(path[:])
            return
        letters = self.lettermap[int(digits[floor])]
        for letter in letters:
            path+=letter
            self.backtrack(floor+1,path,digits)
            path = path[:-1]
    def letterCombinations(self, digits):
        if not digits:
            return []
        self.lettermap= ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
        self.res = []
        self.backtrack(0,"",digits)
        return self.res

回溯问题一律看成横向竖向都进行的树即可。
本题中第一个难点就是如何才能将数字与其所有可能对应的字母映射在一起,那最好的方法就是用列表,列表的索引对应数字,列表的元素就是该索引数字对应的字符串,这样就可以直接用数字映射字母了。
第二个难点就是每一层都在做什么,首先中止条件就是层数到了,那这个层数就一定对应着所给数字的长度,那么就可以使用一个统一的索引:floor,既能表示回溯的层数,又能表示现在遍历数字串的索引,记住一定要在每一层回溯之前先进行回溯中止的判断。
之后就要考虑如何向下传递,首先必须将对应的层数传递下去,这个层数从第0层开始(这样是方便对应数字的索引)一直到第len(digits)层结束,其实所有的数字在第len(digits)-1层就已经遍历完了,那么进入到第len(digits)层之后,就会先判断层数是否等于len(digits),这样就可以将此时的path加入到res中,并且返回。
最后,这道题其实可以使用隐式回溯,是因为这道题向下传递的是字符串,而并非指向一个列表的变量,因此可以使用隐式回溯。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值