Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2f86a5c
Update 0701.二叉搜索树中的插入操作.md
jianghongcheng May 25, 2023
343e077
Update 0216.组合总和III.md
jianghongcheng May 26, 2023
89e9d75
Update 0077.组合.md
jianghongcheng May 26, 2023
4d48c45
Update 0077.组合优化.md
jianghongcheng May 26, 2023
847c60a
Update 0017.电话号码的字母组合.md
jianghongcheng May 26, 2023
2c51420
Update 0039.组合总和.md
jianghongcheng May 26, 2023
20db57f
Update 0040.组合总和II.md
jianghongcheng May 26, 2023
59742e5
Update 0040.组合总和II.md
jianghongcheng May 26, 2023
4586386
Update 0131.分割回文串.md
jianghongcheng May 27, 2023
78445d7
Update 0131.分割回文串.md
jianghongcheng May 27, 2023
51c8976
Update 0093.复原IP地址.md
jianghongcheng May 27, 2023
d45c141
Update 0078.子集.md
jianghongcheng May 27, 2023
5801ae7
Update 0090.子集II.md
jianghongcheng May 27, 2023
eb72f26
Update 0491.递增子序列.md
jianghongcheng May 28, 2023
7e3fc8e
Update 0491.递增子序列.md
jianghongcheng May 28, 2023
a6c95b7
Update 0491.递增子序列.md
jianghongcheng May 28, 2023
b033a08
Update 0046.全排列.md
jianghongcheng May 28, 2023
fd2608a
Update 0047.全排列II.md
jianghongcheng May 28, 2023
19ecde0
Update 回溯算法去重问题的另一种写法.md
jianghongcheng May 28, 2023
498395d
Update 0332.重新安排行程.md
jianghongcheng May 28, 2023
93e0a18
Update 0051.N皇后.md
jianghongcheng May 28, 2023
11581df
Update 0455.分发饼干.md
jianghongcheng May 28, 2023
18a406e
Update 0376.摆动序列.md
jianghongcheng May 28, 2023
996ddbe
Merge pull request #2098 from jianghongcheng/master
youngyangyang04 May 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 129 additions & 74 deletions problems/0017.电话号码的字母组合.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,99 +287,154 @@ class Solution {
```

## Python
**回溯**
回溯
```python
class Solution:
def __init__(self):
self.answers: List[str] = []
self.answer: str = ''
self.letter_map = {
'2': 'abc',
'3': 'def',
'4': 'ghi',
'5': 'jkl',
'6': 'mno',
'7': 'pqrs',
'8': 'tuv',
'9': 'wxyz'
}

def letterCombinations(self, digits: str) -> List[str]:
self.answers.clear()
if not digits: return []
self.letterMap = [
"", # 0
"", # 1
"abc", # 2
"def", # 3
"ghi", # 4
"jkl", # 5
"mno", # 6
"pqrs", # 7
"tuv", # 8
"wxyz" # 9
]
self.result = []
self.s = ""

def backtracking(self, digits, index):
if index == len(digits):
self.result.append(self.s)
return
digit = int(digits[index]) # 将索引处的数字转换为整数
letters = self.letterMap[digit] # 获取对应的字符集
for i in range(len(letters)):
self.s += letters[i] # 处理字符
self.backtracking(digits, index + 1) # 递归调用,注意索引加1,处理下一个数字
self.s = self.s[:-1] # 回溯,删除最后添加的字符

def letterCombinations(self, digits):
if len(digits) == 0:
return self.result
self.backtracking(digits, 0)
return self.answers
return self.result

```
回溯精简(版本一)
```python
class Solution:
def __init__(self):
self.letterMap = [
"", # 0
"", # 1
"abc", # 2
"def", # 3
"ghi", # 4
"jkl", # 5
"mno", # 6
"pqrs", # 7
"tuv", # 8
"wxyz" # 9
]
self.result = []

def backtracking(self, digits: str, index: int) -> None:
# 回溯函数没有返回值
# Base Case
if index == len(digits): # 当遍历穷尽后的下一层时
self.answers.append(self.answer)
return
# 单层递归逻辑
letters: str = self.letter_map[digits[index]]
def getCombinations(self, digits, index, s):
if index == len(digits):
self.result.append(s)
return
digit = int(digits[index])
letters = self.letterMap[digit]
for letter in letters:
self.answer += letter # 处理
self.backtracking(digits, index + 1) # 递归至下一层
self.answer = self.answer[:-1] # 回溯
self.getCombinations(digits, index + 1, s + letter)

def letterCombinations(self, digits):
if len(digits) == 0:
return self.result
self.getCombinations(digits, 0, "")
return self.result

```
**回溯简化**
回溯精简(版本二)
```python
class Solution:
def __init__(self):
self.answers: List[str] = []
self.letter_map = {
'2': 'abc',
'3': 'def',
'4': 'ghi',
'5': 'jkl',
'6': 'mno',
'7': 'pqrs',
'8': 'tuv',
'9': 'wxyz'
}

def letterCombinations(self, digits: str) -> List[str]:
self.answers.clear()
if not digits: return []
self.backtracking(digits, 0, '')
return self.answers
self.letterMap = [
"", # 0
"", # 1
"abc", # 2
"def", # 3
"ghi", # 4
"jkl", # 5
"mno", # 6
"pqrs", # 7
"tuv", # 8
"wxyz" # 9
]

def backtracking(self, digits: str, index: int, answer: str) -> None:
# 回溯函数没有返回值
# Base Case
if index == len(digits): # 当遍历穷尽后的下一层时
self.answers.append(answer)
return
# 单层递归逻辑
letters: str = self.letter_map[digits[index]]
def getCombinations(self, digits, index, s, result):
if index == len(digits):
result.append(s)
return
digit = int(digits[index])
letters = self.letterMap[digit]
for letter in letters:
self.backtracking(digits, index + 1, answer + letter) # 递归至下一层 + 回溯
self.getCombinations(digits, index + 1, s + letter, result)

def letterCombinations(self, digits):
result = []
if len(digits) == 0:
return result
self.getCombinations(digits, 0, "", result)
return result


```
**使用itertools**

回溯优化使用列表
```python
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
import itertools
if not digits:
return list()

phoneMap = {
"2": "abc",
"3": "def",
"4": "ghi",
"5": "jkl",
"6": "mno",
"7": "pqrs",
"8": "tuv",
"9": "wxyz",
}
def __init__(self):
self.letterMap = [
"", # 0
"", # 1
"abc", # 2
"def", # 3
"ghi", # 4
"jkl", # 5
"mno", # 6
"pqrs", # 7
"tuv", # 8
"wxyz" # 9
]

def getCombinations(self, digits, index, path, result):
if index == len(digits):
result.append(''.join(path))
return
digit = int(digits[index])
letters = self.letterMap[digit]
for letter in letters:
path.append(letter)
self.getCombinations(digits, index + 1, path, result)
path.pop()

def letterCombinations(self, digits):
result = []
if len(digits) == 0:
return result
self.getCombinations(digits, 0, [], result)
return result



groups = (phoneMap[digit] for digit in digits)
return ["".join(combination) for combination in itertools.product(*groups)]
```



## Go

主要在于递归中传递下一个数字
Expand Down
130 changes: 78 additions & 52 deletions problems/0039.组合总和.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,75 +273,101 @@ class Solution {

## Python

**回溯**
回溯(版本一)

```python
class Solution:
def __init__(self):
self.path = []
self.paths = []

def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
'''
因为本题没有组合数量限制,所以只要元素总和大于target就算结束
'''
self.path.clear()
self.paths.clear()
self.backtracking(candidates, target, 0, 0)
return self.paths

def backtracking(self, candidates: List[int], target: int, sum_: int, start_index: int) -> None:
# Base Case
if sum_ == target:
self.paths.append(self.path[:]) # 因为是shallow copy,所以不能直接传入self.path
def backtracking(self, candidates, target, total, startIndex, path, result):
if total > target:
return
if sum_ > target:
if total == target:
result.append(path[:])
return

# 单层递归逻辑
for i in range(start_index, len(candidates)):
sum_ += candidates[i]
self.path.append(candidates[i])
self.backtracking(candidates, target, sum_, i) # 因为无限制重复选取,所以不是i+1
sum_ -= candidates[i] # 回溯
self.path.pop() # 回溯
for i in range(startIndex, len(candidates)):
total += candidates[i]
path.append(candidates[i])
self.backtracking(candidates, target, total, i, path, result) # 不用i+1了,表示可以重复读取当前的数
total -= candidates[i]
path.pop()

def combinationSum(self, candidates, target):
result = []
self.backtracking(candidates, target, 0, 0, [], result)
return result

```

**剪枝回溯**
回溯剪枝(版本一)

```python
class Solution:
def __init__(self):
self.path = []
self.paths = []

def backtracking(self, candidates, target, total, startIndex, path, result):
if total == target:
result.append(path[:])
return

for i in range(startIndex, len(candidates)):
if total + candidates[i] > target:
break
total += candidates[i]
path.append(candidates[i])
self.backtracking(candidates, target, total, i, path, result)
total -= candidates[i]
path.pop()

def combinationSum(self, candidates, target):
result = []
candidates.sort() # 需要排序
self.backtracking(candidates, target, 0, 0, [], result)
return result

```

回溯(版本二)

```python
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
'''
因为本题没有组合数量限制,所以只要元素总和大于target就算结束
'''
self.path.clear()
self.paths.clear()
result =[]
self.backtracking(candidates, target, 0, [], result)
return result
def backtracking(self, candidates, target, startIndex, path, result):
if target == 0:
result.append(path[:])
return
if target < 0:
return
for i in range(startIndex, len(candidates)):
path.append(candidates[i])
self.backtracking(candidates, target - candidates[i], i, path, result)
path.pop()

# 为了剪枝需要提前进行排序
candidates.sort()
self.backtracking(candidates, target, 0, 0)
return self.paths
```

回溯剪枝(版本二)

def backtracking(self, candidates: List[int], target: int, sum_: int, start_index: int) -> None:
# Base Case
if sum_ == target:
self.paths.append(self.path[:]) # 因为是shallow copy,所以不能直接传入self.path
```python
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
result =[]
candidates.sort()
self.backtracking(candidates, target, 0, [], result)
return result
def backtracking(self, candidates, target, startIndex, path, result):
if target == 0:
result.append(path[:])
return
# 单层递归逻辑
# 如果本层 sum + condidates[i] > target,就提前结束遍历,剪枝
for i in range(start_index, len(candidates)):
if sum_ + candidates[i] > target:
return
sum_ += candidates[i]
self.path.append(candidates[i])
self.backtracking(candidates, target, sum_, i) # 因为无限制重复选取,所以不是i-1
sum_ -= candidates[i] # 回溯
self.path.pop() # 回溯

for i in range(startIndex, len(candidates)):
if target - candidates[i] < 0:
break
path.append(candidates[i])
self.backtracking(candidates, target - candidates[i], i, path, result)
path.pop()

```

## Go
Expand Down
Loading