代码随想录算法训练营第三十二天 | 332.重新安排行程、51.N皇后、33.解数独、总结

目录

332.重新安排行程

思路

代码

51.N皇后

思路

代码

37.解数独

思路

代码

总结


332.重新安排行程

题目链接:
思路

        说实话,第一次见到这个题挺懵逼的,我感觉这好像就是图的深度优先搜索,一写起来根本不会写,甚至还有带回路的图。。。 (每日崩溃1/1)最后是照着答案敲了一遍,所以思路还是看链接吧。

代码
from collections import defaultdict

class Solution:
    def findItinerary(self, tickets):
        targets = defaultdict(list)  # 创建默认字典,用于存储机场映射关系
        for ticket in tickets:
            targets[ticket[0]].append(ticket[1])  # 将机票输入到字典中
        
        for key in targets:
            targets[key].sort(reverse=True)  # 对到达机场列表进行字母逆序排序
        
        result = []
        self.backtracking("JFK", targets, result)  # 调用回溯函数开始搜索路径
        return result[::-1]  # 返回逆序的行程路径
    
    def backtracking(self, airport, targets, result):
        while targets[airport]:  # 当机场还有可到达的机场时
            next_airport = targets[airport].pop()  # 弹出下一个机场
            self.backtracking(next_airport, targets, result)  # 递归调用回溯函数进行深度优先搜索
        result.append(airport)  # 将当前机场添加到行程路径中

51.N皇后

思路

        这道题很经典了吧[Doge],入门必备的那种,这道题比下一道容易的原因是每次放皇后时根本不需要担心两个皇后会不会出现在同一行,(因为每次递归行数都会+1),相当于只要考虑是不是同一列上和主副对角线上有没有就可以了。

代码
class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        result = []  # 存储最终结果的二维字符串数组

        chessboard = ['.' * n for _ in range(n)]  # 初始化棋盘
        self.backtracking(n, 0, chessboard, result)  # 回溯求解
        return [[''.join(row) for row in solution] for solution in result]  # 返回结果集

    def backtracking(self, n: int, row: int, chessboard: List[str], result: List[List[str]]) -> None:
        if row == n:
            result.append(chessboard[:])  # 棋盘填满,将当前解加入结果集
            return

        for col in range(n):
            if self.isValid(row, col, chessboard):
                chessboard[row] = chessboard[row][:col] + 'Q' + chessboard[row][col+1:]  # 放置皇后
                self.backtracking(n, row + 1, chessboard, result)  # 递归到下一行
                chessboard[row] = chessboard[row][:col] + '.' + chessboard[row][col+1:]  # 回溯,撤销当前位置的皇后

    def isValid(self, row: int, col: int, chessboard: List[str]) -> bool:
        # 检查列
        for i in range(row):
            if chessboard[i][col] == 'Q':
                return False  # 当前列已经存在皇后,不合法

        # 检查 45 度角是否有皇后
        i, j = row - 1, col - 1
        while i >= 0 and j >= 0:
            if chessboard[i][j] == 'Q':
                return False  # 左上方向已经存在皇后,不合法
            i -= 1
            j -= 1

        # 检查 135 度角是否有皇后
        i, j = row - 1, col + 1
        while i >= 0 and j < len(chessboard):
            if chessboard[i][j] == 'Q':
                return False  # 右上方向已经存在皇后,不合法
            i -= 1
            j += 1

        return True  # 当前位置合法

37.解数独

思路

        第一眼看,我嘞个豆。。。这道题有点像纸老虎,冷静思考之后其实也还行。就是二维遍历整个棋盘,对每一个空位进行尝试,然后递归到下个空位进行尝试,如果成功一直递归到最后,如果失败就返回。check()函数的三种情况仔细想想不难考虑。

代码
class Solution:
    def solveSudoku(self, board: List[List[str]]) -> None:
        self.backtracking(board)
        """
        Do not return anything, modify board in-place instead.
        """

    def backtracking(self, board):
         # 若有解,返回True;若无解,返回False
        for row in range(9):
            for col in range(9):
                 # 若空格内已有数字,跳过
                if board[row][col] != ".":
                    continue
                for val in range(1, 10):
                    val = str(val)
                    if self.check(row, col, val, board):
                        board[row][col] = val  # 细节str()输出里面全都是str,不能用int,此处我上面统一加过了。
                        # 下面这里最关键,要写成if self。backtracking(): return True
                        if self.backtracking(board):
                            return True
                        # 如果上面没有return True一层层回溯的的话,下面这一行就会生效,就回溯了,结束就无法输出了。
                        board[row][col] = "."
                # 若数字1-9都不能成功填入空格,返回False无解
                return False
        return True

    def check(self, row, col, val, board):
        # 判断同一行是否冲突
        for i in range(9):
            if board[row][i] == val:
                return False
        # 判断同一列是否冲突
        for i in range(9):
            if board[i][col] == 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] == val:
                    return False

        return True

总结


回溯到这里就正式结束了,后面开始学贪心算法。go go go

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值