算法工程师第十九天(理论基础 组合 组合总和III 电话号码的字母组合)

参考文献 代码随想录

一、组合

给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

示例 1:

输入:n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

示例 2:

输入:n = 1, k = 1
输出:[[1]]

提示:

  • 1 <= n <= 20
  • 1 <= k <= n

问题分析:回溯主要考虑到参数和处理逻辑

    def __init__(self):
        self.ans = []
        self.stack = []
    def combine(self, n, k):
        """
        :type n: int
        :type k: int
        :rtype: List[List[int]]
        """
        self.backstrking(1, n, k)
        return self.ans
    def backstrking(self,start, n, k):
        if len(self.stack) == k:
            self.ans.append(self.stack[:])
            return
        for i in range(start, n + 1):
            self.stack.append(i)
            self.backstrking(i + 1, n,  k)
            self.stack.pop()

 剪枝

class Solution(object):
    def __init__(self):
        self.ans = []
        self.stack = []
    def combine(self, n, k):
        """
        :type n: int
        :type k: int
        :rtype: List[List[int]]
        """
        self.backstrking(1, n, k)
        return self.ans
    def backstrking(self,start, n, k):
        if len(self.stack) == k:
            self.ans.append(self.stack[:])
            return
        for i in range(start,  n - (k - len(self.stack)) + 2):  # n - (k - len(self.stack)) + 2。(k - len(self.stack)这个试求,还需要多少个元素n - (k - len(self.stack))最多的起始遍历位子(最多遍历到当前这个数,往后遍历,没有满足要求)
            self.stack.append(i)
            self.backstrking(i + 1, n, k)
            self.stack.pop()

二、组合总和 III

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

  • 只使用数字1到9
  • 每个数字 最多使用一次 

返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

示例 1:

输入: k = 3, n = 7
输出: [[1,2,4]]
解释:
1 + 2 + 4 = 7
没有其他符合的组合了。

示例 2:

输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
解释:
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
没有其他符合的组合了。

示例 3:

输入: k = 4, n = 1
输出: []
解释: 不存在有效的组合。
在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。
class Solution(object):
    def __init__(self):
        self.ans = []
        self.stack = []
    def combinationSum3(self, k, n):
        """
        :type k: int
        :type n: int
        :rtype: List[List[int]]
        """
        self.backstrikng(1, k, n)
        return self.ans
    def backstrikng(self, startIndex, k, n):
        if sum(self.stack) == n and len(self.stack) == k:
            self.ans.append(self.stack[:])
        for i in range(startIndex, 10):
            self.stack.append(i)
            self.backstrikng(i + 1, k , n)
            self.stack.pop()

剪枝

class Solution(object):
    def __init__(self):
        self.ans = []
        self.stack = []
    def combinationSum3(self, k, n):
        """
        :type k: int
        :type n: int
        :rtype: List[List[int]]
        """
        self.backstrikng(1, k, n)
        return self.ans
    def backstrikng(self, startIndex, k, n):
        if sum(self.stack) > n:  # 一旦返现和大于n,那么就结束掉
            return
        if sum(self.stack) == n and len(self.stack) == k:
            self.ans.append(self.stack[:])
        for i in range(startIndex, 9 - (k - len(self.stack)) + 2):  # 为什么要加2,为什么首先是加1,为什么要加一呢?因为当k = 2, self.stack.size == 0,那么后面就只能取到8,然后要加1才能取到这样才能组合1到9的组合问题
            self.stack.append(i)
            self.backstrikng(i + 1, k , n)
            self.stack.pop()

三、电话号码的字母组合

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

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

示例 1:

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

输入:digits = ""
输出:[]

示例 3:

输入:digits = "2"
输出:["a","b","c"]

问题分析:上面2题都是用了startIndex,这个是控制不重复元素,并且是在一个集合里,而本题不一样的是在多个集合求组合问题,然后我们定义一index来记录访问到了那个结合,如果index等于digits的长度,那么说明,已经遍历完全部结合,为什么index 是从0开始呢,因为要遍历digits中的按键,那么结束,为什么要等于长度呢?因为,要遍历完digits,如果不等于它的长度,那么当遍历到最后一个按键是,将退出遍历,那么就不满足题目需要。

class Solution(object):
    def __init__(self):
        self.dic = {
            1:'',
            2:"abc",
            3:"def",
            4:"ghi",
            5:"jkl",
            6:"mno",
            7:"pqrs",
            8:"tuv",
            9:"wxyz"
        }
        self.ans = []
        self.stack = []
    def letterCombinations(self, digits):
        """
        :type digits: str
        :rtype: List[str]
        """
        if not digits:
            return self.ans
       
        self.backstriking(digits, 0)
        return self.ans
    def backstriking(self, digits, index):
        if index == len(digits):
            self.ans.append("".join(self.stack))
            return
        digit = int(digits[index])  # 获取对应的按键
        strd = self.dic[digit]  # 获取对应的字符串  多个集合组合问题
        for i in range(len(strd)):
            self.stack.append(strd[i])
            self.backstriking(digits, index + 1)
            self.stack.pop()

简化版本

class Solution(object):
    def __init__(self):
        self.dic = {
            1:'',
            2:"abc",
            3:"def",
            4:"ghi",
            5:"jkl",
            6:"mno",
            7:"pqrs",
            8:"tuv",
            9:"wxyz"
        }
        self.ans = []
    def letterCombinations(self, digits):
        """
        :type digits: str
        :rtype: List[str]
        """
        if not digits:
            return self.ans
        self.backstriking(digits, 0, '')
        return self.ans

    def backstriking(self, digits, index, s):
        if index == len(digits):
            self.ans.append(s)
            return

        digit = int(digits[index])  # 获取对应的按键
        strd = self.dic[digit]  # 获取对应的字符串  2个集合组合问题
        
        for i in range(len(strd)):
            self.backstriking(digits, index + 1, s + strd[i])
    

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值