1、电话号码的字母组合(17)
题目描述:
【中等】
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例一:
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
思路分析
1、对与“23”我们不难推断出它的解为下图:
- 这显然是在树形结构求树叶的全部解,在树形结构中找全部的解,通常使用回溯算法。
2、先写出数字与字符一一映射的字典,phone={‘数字(key)’:‘对应字母(value)’}。
3、在这道题中,由于每个数字对应的每个字母都可能进入字母组合,因此不存在不可行的解,直接穷举所有的解即可。
定义回溯函数:
- 回溯出口:如果回溯次数与数字字符串长度一致,就是一个可行解,将其存储在结果表中。
- 回溯主体:对于每一个数字字符串中的数字所对应的字母做以下操作:
- 将其添加到一个可行解列表中
- 对于下一个字符进行回溯操作
- 取消标记,状态返回即恢复可行解列表为空
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
if not digits:
return []
#定义数字字符映射字典
phonemap={
"2": "abc",
"3": "def",
"4": "ghi",
"5": "jkl",
"6": "mno",
"7": "pqrs",
"8": "tuv",
"9": "wxyz",
}
#存储可行解
combination=[]
#存储最终解,集合可行解
combinations=[]
#定义回溯函数
def backtrack(i):
#回溯出口:满足条件的解
#如果回溯次数等于数字字符串的长度,就是一个可行解
if i==len(digits):
combinations.append("".join(combination))
#回溯主体
else:
digit=digits[i]
for letter in phonemap[digit]:
combination.append(letter)
#对数字字符串的下一个数字进行回溯
backtrack(i+1)
#取消标记,状态返回,不再走这条路
combination.pop()#combination再次为空
backtrack(0)
return combinations
- 时间复杂度: O ( 3 m + 4 n ) O(3^m+4^n) O(3m+4n),其中m是输入中对应3个字母的数字个数,n是输入中对应4个字母的数字个数。
- 空间复杂度: O ( m + n ) O(m+n) O(m+n)
2、括号生成(22)
题目描述:
【中等】
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
思路分析
3、复原IP地址(93)
题目描述:
【中等】
给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。
有效的 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 ‘.’ 分隔。
例如:“0.1.2.201” 和 “192.168.1.1” 是 有效的 IP 地址,但是 “0.011.255.245”、“192.168.1.312” 和 “192.168@1.1” 是 无效的 IP 地址。
示例一:
输入:s = "25525511135"
输出:["255.255.11.135","255.255.111.35"]
思路分析
1、有效的 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),因此我们可以首先以1,2,3个字符进行第一次分割然后查看后面的是否能够满足,一旦发现不满,就将这一路封死。如下图:
2、需要进行剪枝情况:
1、一开始,字符串的长度小于 4 或者大于 12 ,一定不能拼凑出合法的 ip 地址(这一点可以一般化到中间结点的判断中,以产生剪枝行为);
2、每一个结点可以选择截取的方法只有 3 种:截 1 位、截 2 位、截 3 位,因此每一个结点可以生长出的分支最多只有 3 条分支;
根据截取出来的字符串判断是否是合理的 ip 段,这里写法比较多,可以先截取,再转换成 int ,再判断。我采用的做法是先转成 int,是合法的 ip 段数值以后,再截取。
3、由于 ip 段最多就 4 个段,因此这棵三叉树最多 4 层,这个条件作为递归终止条件之一;
4、每一个结点表示了求解这个问题的不同阶段,需要的状态变量有:
class Solution:
def restoreIpAddresses(self, s: str) -> List[str]:
result = []
def addOnePoint(src, dst, cnt):
if not src and cnt == 4:
result.append(dst[:-1])
if src and cnt < 4:
for i in range(1, 4):
if len(src) >= i and 0 <= int(src[:i]) <= 255 and str(int(src[:i])) == src[:i]:
addOnePoint(src[i:], dst + src[:i] + '.', cnt + 1)
addOnePoint(s, '', 0)
return result