Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c3cc5fb

Browse files
Update
2 parents 104ba7c + bed1f5a commit c3cc5fb

File tree

61 files changed

+1995
-612
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1995
-612
lines changed

problems/0017.电话号码的字母组合.md

Lines changed: 62 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -282,61 +282,74 @@ class Solution {
282282
```
283283

284284
## Python
285-
286-
```Python
285+
**回溯**
286+
```python3
287287
class Solution:
288-
ans = []
289-
s = ''
290-
letterMap = {
291-
'2': 'abc',
292-
'3': 'def',
293-
'4': 'ghi',
294-
'5': 'jkl',
295-
'6': 'mno',
296-
'7': 'pqrs',
297-
'8': 'tuv',
298-
'9': 'wxyz'
299-
}
288+
def __init__(self):
289+
self.answers: List[str] = []
290+
self.answer: str = ''
291+
self.letter_map = {
292+
'2': 'abc',
293+
'3': 'def',
294+
'4': 'ghi',
295+
'5': 'jkl',
296+
'6': 'mno',
297+
'7': 'pqrs',
298+
'8': 'tuv',
299+
'9': 'wxyz'
300+
}
300301

301-
def letterCombinations(self, digits):
302-
self.ans.clear()
303-
if digits == '':
304-
return self.ans
302+
def letterCombinations(self, digits: str) -> List[str]:
303+
self.answers.clear()
304+
if not digits: return []
305305
self.backtracking(digits, 0)
306-
return self.ans
307-
308-
def backtracking(self, digits, index):
309-
if index == len(digits):
310-
self.ans.append(self.s)
311-
return
312-
else:
313-
letters = self.letterMap[digits[index]] # 取出数字对应的字符集
314-
for letter in letters:
315-
self.s = self.s + letter # 处理
316-
self.backtracking(digits, index + 1)
317-
self.s = self.s[:-1] # 回溯
306+
return self.answers
307+
308+
def backtracking(self, digits: str, index: int) -> None:
309+
# 回溯函数没有返回值
310+
# Base Case
311+
if index == len(digits): # 当遍历穷尽后的下一层时
312+
self.answers.append(self.answer)
313+
return
314+
# 单层递归逻辑
315+
letters: str = self.letter_map[digits[index]]
316+
for letter in letters:
317+
self.answer += letter # 处理
318+
self.backtracking(digits, index + 1) # 递归至下一层
319+
self.answer = self.answer[:-1] # 回溯
318320
```
319-
320-
python3:
321-
322-
```py
321+
**回溯简化**
322+
```python3
323323
class Solution:
324+
def __init__(self):
325+
self.answers: List[str] = []
326+
self.letter_map = {
327+
'2': 'abc',
328+
'3': 'def',
329+
'4': 'ghi',
330+
'5': 'jkl',
331+
'6': 'mno',
332+
'7': 'pqrs',
333+
'8': 'tuv',
334+
'9': 'wxyz'
335+
}
336+
324337
def letterCombinations(self, digits: str) -> List[str]:
325-
res = []
326-
s = ""
327-
letterMap = ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
328-
if not len(digits): return res
329-
def backtrack(digits,index, s):
330-
if index == len(digits):
331-
return res.append(s)
332-
digit = int(digits[index]) #将index指向的数字转为int
333-
letters = letterMap[digit] #取数字对应的字符集
334-
for i in range(len(letters)):
335-
s += letters[i]
336-
backtrack(digits, index+1, s) #递归,注意index+1,一下层要处理下一个数字
337-
s = s[:-1] #回溯
338-
backtrack(digits, 0, s)
339-
return res
338+
self.answers.clear()
339+
if not digits: return []
340+
self.backtracking(digits, 0, '')
341+
return self.answers
342+
343+
def backtracking(self, digits: str, index: int, answer: str) -> None:
344+
# 回溯函数没有返回值
345+
# Base Case
346+
if index == len(digits): # 当遍历穷尽后的下一层时
347+
self.answers.append(answer)
348+
return
349+
# 单层递归逻辑
350+
letters: str = self.letter_map[digits[index]]
351+
for letter in letters:
352+
self.backtracking(digits, index + 1, answer + letter) # 递归至下一层 + 回溯
340353
```
341354

342355

problems/0019.删除链表的倒数第N个节点.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
* fast首先走n + 1步 ,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作),如图:
5151
<img src='https://code-thinking.cdn.bcebos.com/pics/19.%E5%88%A0%E9%99%A4%E9%93%BE%E8%A1%A8%E7%9A%84%E5%80%92%E6%95%B0%E7%AC%ACN%E4%B8%AA%E8%8A%82%E7%82%B91.png' width=600> </img></div>
5252

53-
* fast和slow同时移动,之道fast指向末尾,如题:
53+
* fast和slow同时移动,直到fast指向末尾,如题:
5454
<img src='https://code-thinking.cdn.bcebos.com/pics/19.%E5%88%A0%E9%99%A4%E9%93%BE%E8%A1%A8%E7%9A%84%E5%80%92%E6%95%B0%E7%AC%ACN%E4%B8%AA%E8%8A%82%E7%82%B92.png' width=600> </img></div>
5555

5656
* 删除slow指向的下一个节点,如图:

problems/0028.实现strStr.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ next数组就可以是前缀表,但是很多实现都是把前缀表统一减
215215

216216
其实**这并不涉及到KMP的原理,而是具体实现,next数组即可以就是前缀表,也可以是前缀表统一减一(右移一位,初始位置为-1)。**
217217

218-
后面我会提供两种不同的实现代码,大家就明白了了
218+
后面我会提供两种不同的实现代码,大家就明白了
219219

220220
# 使用next数组来匹配
221221

problems/0035.搜索插入位置.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,24 @@ class Solution {
227227
}
228228
}
229229
```
230-
230+
Golang:
231+
```golang
232+
// 第一种二分法
233+
func searchInsert(nums []int, target int) int {
234+
l, r := 0, len(nums) - 1
235+
for l <= r{
236+
m := l + (r - l)/2
237+
if nums[m] == target{
238+
return m
239+
}else if nums[m] > target{
240+
r = m - 1
241+
}else{
242+
l = m + 1
243+
}
244+
}
245+
return r + 1
246+
}
247+
```
231248

232249
### Python
233250
```python3

problems/0037.解数独.md

Lines changed: 30 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -292,85 +292,40 @@ class Solution:
292292
"""
293293
Do not return anything, modify board in-place instead.
294294
"""
295-
def backtrack(board):
296-
for i in range(len(board)): #遍历行
297-
for j in range(len(board[0])): #遍历列
298-
if board[i][j] != ".": continue
299-
for k in range(1,10): #(i, j) 这个位置放k是否合适
300-
if isValid(i,j,k,board):
301-
board[i][j] = str(k) #放置k
302-
if backtrack(board): return True #如果找到合适一组立刻返回
303-
board[i][j] = "." #回溯,撤销k
304-
return False #9个数都试完了,都不行,那么就返回false
305-
return True #遍历完没有返回false,说明找到了合适棋盘位置了
306-
def isValid(row,col,val,board):
307-
for i in range(9): #判断行里是否重复
308-
if board[row][i] == str(val):
309-
return False
310-
for j in range(9): #判断列里是否重复
311-
if board[j][col] == str(val):
312-
return False
313-
startRow = (row // 3) * 3
314-
startcol = (col // 3) * 3
315-
for i in range(startRow,startRow + 3): #判断9方格里是否重复
316-
for j in range(startcol,startcol + 3):
317-
if board[i][j] == str(val):
318-
return False
319-
return True
320-
backtrack(board)
321-
```
322-
323-
### Python3
324-
325-
```python3
326-
class Solution:
327-
def __init__(self) -> None:
328-
self.board = []
329-
330-
def isValid(self, row: int, col: int, target: int) -> bool:
331-
for idx in range(len(self.board)):
332-
# 同列是否重复
333-
if self.board[idx][col] == str(target):
295+
self.backtracking(board)
296+
297+
def backtracking(self, board: List[List[str]]) -> bool:
298+
# 若有解,返回True;若无解,返回False
299+
for i in range(len(board)): # 遍历行
300+
for j in range(len(board[0])): # 遍历列
301+
# 若空格内已有数字,跳过
302+
if board[i][j] != '.': continue
303+
for k in range(1, 10):
304+
if self.is_valid(i, j, k, board):
305+
board[i][j] = str(k)
306+
if self.backtracking(board): return True
307+
board[i][j] = '.'
308+
# 若数字1-9都不能成功填入空格,返回False无解
334309
return False
335-
# 同行是否重复
336-
if self.board[row][idx] == str(target):
310+
return True # 有解
311+
312+
def is_valid(self, row: int, col: int, val: int, board: List[List[str]]) -> bool:
313+
# 判断同一行是否冲突
314+
for i in range(9):
315+
if board[row][i] == str(val):
337316
return False
338-
# 9宫格里是否重复
339-
box_row, box_col = (row // 3) * 3 + idx // 3, (col // 3) * 3 + idx % 3
340-
if self.board[box_row][box_col] == str(target):
317+
# 判断同一列是否冲突
318+
for j in range(9):
319+
if board[j][col] == str(val):
341320
return False
321+
# 判断同一九宫格是否有冲突
322+
start_row = (row // 3) * 3
323+
start_col = (col // 3) * 3
324+
for i in range(start_row, start_row + 3):
325+
for j in range(start_col, start_col + 3):
326+
if board[i][j] == str(val):
327+
return False
342328
return True
343-
344-
def getPlace(self) -> List[int]:
345-
for row in range(len(self.board)):
346-
for col in range(len(self.board)):
347-
if self.board[row][col] == ".":
348-
return [row, col]
349-
return [-1, -1]
350-
351-
def isSolved(self) -> bool:
352-
row, col = self.getPlace() # 找个空位置
353-
354-
if row == -1 and col == -1: # 没有空位置,棋盘被填满的
355-
return True
356-
357-
for i in range(1, 10):
358-
if self.isValid(row, col, i): # 检查这个空位置放i,是否合适
359-
self.board[row][col] = str(i) # 放i
360-
if self.isSolved(): # 合适,立刻返回, 填下一个空位置。
361-
return True
362-
self.board[row][col] = "." # 不合适,回溯
363-
364-
return False # 空位置没法解决
365-
366-
def solveSudoku(self, board: List[List[str]]) -> None:
367-
"""
368-
Do not return anything, modify board in-place instead.
369-
"""
370-
if board is None or len(board) == 0:
371-
return
372-
self.board = board
373-
self.isSolved()
374329
```
375330

376331
### Go

problems/0039.组合总和.md

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -264,25 +264,73 @@ class Solution {
264264
}
265265
```
266266

267-
## Python
267+
## Python
268+
**回溯**
268269
```python3
269270
class Solution:
271+
def __init__(self):
272+
self.path = []
273+
self.paths = []
274+
275+
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
276+
'''
277+
因为本题没有组合数量限制,所以只要元素总和大于target就算结束
278+
'''
279+
self.path.clear()
280+
self.paths.clear()
281+
self.backtracking(candidates, target, 0, 0)
282+
return self.paths
283+
284+
def backtracking(self, candidates: List[int], target: int, sum_: int, start_index: int) -> None:
285+
# Base Case
286+
if sum_ == target:
287+
self.paths.append(self.path[:]) # 因为是shallow copy,所以不能直接传入self.path
288+
return
289+
if sum_ > target:
290+
return
291+
292+
# 单层递归逻辑
293+
for i in range(start_index, len(candidates)):
294+
sum_ += candidates[i]
295+
self.path.append(candidates[i])
296+
self.backtracking(candidates, target, sum_, i) # 因为无限制重复选取,所以不是i-1
297+
sum_ -= candidates[i] # 回溯
298+
self.path.pop() # 回溯
299+
```
300+
**剪枝回溯**
301+
```python3
302+
class Solution:
303+
def __init__(self):
304+
self.path = []
305+
self.paths = []
306+
270307
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
271-
res = []
272-
path = []
273-
def backtrack(candidates,target,sum,startIndex):
274-
if sum > target: return
275-
if sum == target: return res.append(path[:])
276-
for i in range(startIndex,len(candidates)):
277-
if sum + candidates[i] >target: return #如果 sum + candidates[i] > target 就终止遍历
278-
sum += candidates[i]
279-
path.append(candidates[i])
280-
backtrack(candidates,target,sum,i) #startIndex = i:表示可以重复读取当前的数
281-
sum -= candidates[i] #回溯
282-
path.pop() #回溯
283-
candidates = sorted(candidates) #需要排序
284-
backtrack(candidates,target,0,0)
285-
return res
308+
'''
309+
因为本题没有组合数量限制,所以只要元素总和大于target就算结束
310+
'''
311+
self.path.clear()
312+
self.paths.clear()
313+
314+
# 为了剪枝需要提前进行排序
315+
candidates.sort()
316+
self.backtracking(candidates, target, 0, 0)
317+
return self.paths
318+
319+
def backtracking(self, candidates: List[int], target: int, sum_: int, start_index: int) -> None:
320+
# Base Case
321+
if sum_ == target:
322+
self.paths.append(self.path[:]) # 因为是shallow copy,所以不能直接传入self.path
323+
return
324+
# 单层递归逻辑
325+
# 如果本层 sum + condidates[i] > target,就提前结束遍历,剪枝
326+
for i in range(start_index, len(candidates)):
327+
if sum_ + candidates[i] > target:
328+
return
329+
sum_ += candidates[i]
330+
self.path.append(candidates[i])
331+
self.backtracking(candidates, target, sum_, i) # 因为无限制重复选取,所以不是i-1
332+
sum_ -= candidates[i] # 回溯
333+
self.path.pop() # 回溯
286334
```
287335

288336
## Go

0 commit comments

Comments
 (0)