代码随想录算法训练营第三十天|332. 重新安排行程,51. N 皇后,37. 解数独
332. 重新安排行程
题目链接:重新安排行程
一些错误
一开始的想法是把以"JFK"
都放到start里,然后一条一条去找,最后超时了。
然后就开始想怎么剪枝,初步想法是把start排序一下,如果有一条是True了直接就return了,但是发现这个做法太贪婪了,最考虑了第二站的字典排序,没考虑之后的。所以还是要一个dict来记录所有的票。
记录一下
class Solution:
def findItinerary(self, tickets: List[List[str]]) -> List[str]:
start = {}
for i in range(len(tickets)):
if tickets[i][0] == "JFK":
start[tickets[i][1]] = i
start = sorted(start.items(), key=lambda d:d[0])
def backtracking(tickets,index,used):
if index == len(tickets):
#print(path)
return True
for k in range(len(tickets)):
if (used[k] == False) and (tickets[k][0] == path[-1]):
path.append(tickets[k][1])
used[k] = True
#print(path,used,index)
if backtracking(tickets,(index+1),used):
return True
used[k] = False
path.pop()
for i,j in start:
path = []
used = [False] * len(tickets)
used[j] = True
path.append('JFK')
path.append(i)
if backtracking(tickets,1,used):
return path
正确的做法
代码随想录里是在dictionary里直接pop来阻止死循环的,我还是喜欢use list。
class Solution:
def findItinerary(self, tickets: List[List[str]]) -> List[str]:
t = defaultdict(list)
for i in range(len(tickets)):
t[tickets[i][0]].append([tickets[i][1],i])
for airport in t:
t[airport].sort()
def backtracking(tickets,from_c,index):
if index == len(tickets):
return True
for to_c,i in t[from_c]:
if used[i] == False:
path.append(to_c)
used[i] = True
if backtracking(tickets,to_c,(index+1)):
return True
used[i] = False
path.pop()
path = ['JFK']
used = [False]*len(tickets)
backtracking(tickets,"JFK",0)
return path
还是要合理利用backtrack的输出,并不是只能输出path的。
51. N 皇后
题目链接:N 皇后
一些无脑的做法
写了一个半小时,困得人都傻了。
几个问题:
- used横竖怎么取
used[i][j]
有两条斜边- 怎么剪枝
class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
path = [["."]*n for _ in range(n)]
result = []
used = [[False]*n for _ in range(n)]
def slash(used,i,j):
re = []
while i > 0 and j > 0:
i -= 1
j -= 1
while i < n and j < n:
re.append(used[i][j])
i += 1
j += 1
return re
def slash1(used,i,j):
re = []
while i > 0 and j < (n-1):
i -= 1
j += 1
while j >= 0 and i < n:
re.append(used[i][j])
i += 1
j -= 1
return re
def backtracking(n,index,used):
if index == n:
result.append([''.join(path[i]) for i in range(n)])
return
for i in range(n):
for j in range(n):
re = used[i]
re1 = list(used[_][j] for _ in range(n))
re2 = slash(used,i,j)
re3 = slash1(used,i,j)
if index != i:
break
if (re == [False]*n) and (re1 == [False]*n) and (re2 == [False]*len(re2)) and (re3 == [False]*len(re3)):
path[i][j] = "Q"
used[i][j] = True
backtracking(n,index+1,used)
used[i][j] = False
path[i][j] = "."
backtracking(n,0,used)
return result
前面几个问题都是自己粗心没什么好说。
我的剪枝办法就是,如果不能一行放一个Q那就直接break。
row可以直接写index的
关于isVaild
:
class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
path = [["."]*n for _ in range(n)]
result = []
def isValid(n,path,row,col):
for i in range(n):
if path[i][col] == "Q": #一行放一个所以行不管
return False
for i,j in zip(range(row-1,-1,-1), range(col+1,n,1)):
if path[i][j] == "Q":
return False
for i,j in zip(range(row-1,-1,-1), range(col-1,-1,-1)):
if path[i][j] == "Q":
return False
return True
def backtracking(n,i):
if i == n:
result.append([''.join(path[_]) for _ in range(n)])
return
for j in range(n):
if isValid(n,path,i,j):
path[i][j] = "Q"
backtracking(n,(i+1))
path[i][j] = "."
backtracking(n,0)
return result
37. 解数独
题目链接:解数独
一个index
感觉三个遍历太复杂了,不想做,看了一下自己半年前的做法,收集所有是'.'
的坐标,然后一维来做就可以了。
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
def isVaild(nums,board,row,col):
if nums in board[row]:
return False
for i in range(len(board)):
if nums == board[i][col]:
return False
a = int(row/3)
b = int(col/3)
for i in range((a*3),(a+1)*3):
for j in range((b*3),(b+1)*3):
if nums == board[i][j]:
return False
return True
def fill(board):
result = []
for i in range(len(board)):
for j in range(len(board)):
if board[i][j] == '.':
result.append([i,j])
return result
tofill = fill(board)
def backtracking(board,tofill,index):
if index == len(tofill):
return True
for nums in range(1,10):
row,col = tofill[index]
if isVaild(str(nums),board,row,col):
board[row][col] = str(nums)
if backtracking(board,tofill,(index+1)):
return True
board[row][col] = '.'
return False
backtracking(board,tofill,0)
这个地方要return True
不然后面就回溯了,直接回去点了,就没有答案了。
if backtracking(board,tofill,(index+1)):
return True
三个遍历
一定一定要记得return True
,不然就回溯了!!!
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
def isVaild(nums,board,row,col):
if nums in board[row]:
return False
for i in range(len(board)):
if nums == board[i][col]:
return False
a = int(row/3)
b = int(col/3)
for i in range((a*3),(a+1)*3):
for j in range((b*3),(b+1)*3):
if nums == board[i][j]:
return False
return True
def backtracking(board):
for i in range(len(board)):
for j in range(len(board)):
if board[i][j] == '.':
for nums in range(1,10):
if isVaild(str(nums),board,i,j):
board[i][j] = str(nums)
if backtracking(board):
return True
board[i][j] = '.'
return False
return True
print(backtracking(board))