力扣刷题-python-回溯算法(完结)-2(回溯算法三道困难题)

1)332.重新安排行程

332. 重新安排行程 - 力扣(LeetCode) (leetcode-cn.com)
弄了半天,还看了解释,好歹是弄完了,但是速度有些慢。

from collections import defaultdict
class Solution:
    def findItinerary(self, tickets: list[list[str]]) -> list[str]:
        ticketDict = defaultdict(list)    #创建字典 key是开始 val是结束  然后剪枝
        for start,ender in tickets:
             ticketDict[start].append(ender)
        def backtracking(instart):
            if len(path)==len(tickets)+1:return   #将其他递归跳出
            ticketDict[instart].sort()
            for i in ticketDict[instart]:
                instartnext= ticketDict[instart].pop(0)
                path.append(instartnext)
                if len(path)==len(tickets)+1 and not res: return
                if instartnext in ticketDict:backtracking(instartnext)
                path.pop()
                ticketDict[instart].append(instartnext)

        res, path = [], ['JFK']
        backtracking('JFK')
        return res

好吧,用了别人的办法

class Solution:
    def findItinerary(self, tickets: List[List[str]]) -> List[str]:
        # defaultdic(list) 是为了方便直接append
        tickets_dict = defaultdict(list)
        for item in tickets:
            tickets_dict[item[0]].append(item[1])
        '''
        tickets_dict里面的内容是这样的
         {'JFK': ['SFO', 'ATL'], 'SFO': ['ATL'], 'ATL': ['JFK', 'SFO']})
        '''
        path = ["JFK"]
        def backtracking(start_point):
            # 终止条件
            if len(path) == len(tickets) + 1: return True
            tickets_dict[start_point].sort()
            for _ in tickets_dict[start_point]:
                #必须及时删除,避免出现死循环
                end_point = tickets_dict[start_point].pop(0)
                path.append(end_point)
                # 只要找到一个就可以返回了
                if backtracking(end_point): return True
                path.pop()
                tickets_dict[start_point].append(end_point)

        backtracking("JFK")
        return path

2)51.N皇后

51. N 皇后 - 力扣(LeetCode) (leetcode-cn.com)

class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        def isVaild(path,row, col):
                if 'Q' in path[row]:    #横行
                       return True
                for j in range(n):      #竖行
                    if path[j][col]=='Q':
                        return True
                for j in range(min(row,n-1-col)+1):
                    if path[row-j][col+j]=='Q': #斜向上
                       return True
                for j in range(min(row,col)+1):  #斜右向上
                    if path[row-j][col-j]=='Q':
                       return True
                return False
        def backstacking(path,index):
            if index==n:return res.append([''.join(_) for _ in path])
            for i in range(n):
                if isVaild(path,index,i):continue  #横竖斜存在Q则跳出这次循环
                path[index][i]='Q'
                backstacking(path,index+1)
                path[index][i]='.'
                        
        path=[['.']*n for _ in range(n)] #创建n矩阵
        res=[]
        backstacking(path,0)
        return res

3)解数独

37. 解数独 - 力扣(LeetCode) (leetcode-cn.com)

解数独的和第一题很像,不过第一题 有明显的结束标志,但是这道题没有,所以只能等他循环完成后面加个结束标志return True
if backtrakcing(board):return True 重点是这行,如果下一轮循环或者叫下一个位置点,没有找到,然后就执行下一行,把这次的点换回来,然后就进行下次 for val in range(1,10):

class Solution:
    def solveSudoku(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        def is_valid(row, col, val):
             # 判断同一行是否冲突
             for i in range(9):
                if board[row][i] == str(val):return False
             # 判断同一列是否冲突
             for j in range(9):
                if board[j][col] == str(val):return False
             # 判断同一九宫格是否有冲突
             start_row = (row // 3) * 3
             start_col = (col // 3) * 3
             for i in range(start_row, start_row + 3):
                for j in range(start_col, start_col + 3):
                    if board[i][j] == str(val):return False
             return True
        
        def backtrakcing(board):
            for i in range(len(board)):
                for j in range(len(board[0])):
                    if board[i][j]=='.':
                        for val in range(1,10):
                            if is_valid(i,j,val):
                                board[i][j]=str(val)
                                if backtrakcing(board):return True
                                board[i][j]='.'
                        # 若数字1-9都不能成功填入空格,返回False无解
                        return False #无解
            return True # 有解  全部解完的                                    
        backtrakcing(board)

4)总结

这种复杂的,需要不断实验或者试填的都可以用以下这种形式

        def backtrakcing(参数):
            判断结束:return True
            #可以通过(参数)驱动位置变化
            #或者在for外层加循环体,以及判断来驱动位置变化
            for 循环体:
                填入数值
                if backtrakcing(参数):return True   #重要点
                返回状态
            return False 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值