代码随想录算法训练营第三十天

代码随想录算法训练营第三十天|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
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))      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值