【leetcode52-55图论、56-63回溯】

图论

回溯【56-63】

46.全排列

python 复制代码
class Solution:
    def permute(self, nums):
        result = []
        self.backtracking(nums, [], [False] * len(nums), result)
        return result

    def backtracking(self, nums, path, used, result):
        if len(path) == len(nums):
            result.append(path[:])
            return
            
        for i in range(len(nums)):
            if used[i]:
                continue
            used[i] = True
            path.append(nums[i])
            self.backtracking(nums, path, used, result)
            path.pop()
            used[i] = False

78.子集

python 复制代码
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = []
        self.backtracking(nums, 0, [], res)
        return res
    
    def backtracking(self, nums, startindex, path, res):
        res.append(path[:])
        for i in range(startindex, len(nums)):
            path.append(nums[i])
            self.backtracking(nums, i+1, path, res)
            path.pop()

17.电话号码的字母组合

python 复制代码
class Solution:
    def letterCombinations(self, digits: str) -> List[str]:

        self.mapping = {2:'abc', 3:'def', 4:'ghi', 
                    5:'jkl',6:'mno',7:'pqrs',8:'tuv',9:'wxyz'}
        res = []
        if len(digits)==0:
            return res
        self.backtracking(digits, 0, [],res)
        return res

    def backtracking(self, digits, startindex, path, res):    
        if len(path) == len(digits):
            res.append(''.join(path))  #将结果转换成str
            return 

        #树宽是mapping[index],树高是len(digits)
        ss = self.mapping[int(digits[startindex])]
        for i in ss:
            path.append(i)
            self.backtracking(digits,startindex+1,path,res)
            path.pop()

39.组合总和

candidate元素不重复,一个元素可以重复选取

python 复制代码
'''控制重复选取'''
self.backtracking(candidates, i, path, res, target)
python 复制代码
class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        res = []
        self.backtracking(candidates, 0, [],res,target)
        return res
    
    def backtracking(self, candidates, startindex, path, res, target):
        if target == 0:
            res.append(path[:])
            return 

        if target < 0:
            return 
        
        for i in range(startindex, len(candidates)):
            path.append(candidates[i])
            target -=  candidates[i]
            self.backtracking(candidates, i, path, res, target)
            path.pop()
            target += candidates[i]

22.括号生成

什么时候可以向下搜索:

  1. 插入数量 < n
  2. 左括号插入数量 > 右括号数量
python 复制代码
class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        res = []
        self.backtracking(n, 0, 0, '', res)
        return res

    def backtracking(self, n, left, right, path, res):
        if left == n and right == n:
            res.append(path)
            return
        
        if left<n:
            self.backtracking(n, left+1, right, path+'(', res )
        
        if left > right :
            self.backtracking(n, left, right+1, path+')', res)

79.单词搜索

递归参数

当前元素在矩阵 board 中的行列索引 i 和 j ,当前目标字符在 word 中的索引 k 。

终止条件

  1. 返回 false : (1) 行或列索引越界 (2) 当前矩阵元素与目标字符不同 或 (3) 当前矩阵元素已访问过
  2. 返回 true : k = len(word) - 1 ,即字符串 word 已全部匹配。
python 复制代码
class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        def dfs(i, j, k):
            if not 0 <= i < len(board) or not 0 <= j < len(board[0]) or board[i][j] != word[k]: 
                return False
            if k == len(word) - 1: 
                return True

            board[i][j] = ''   #代表当前元素已经访问过,防止反复访问
            res = dfs(i + 1, j, k + 1) or dfs(i - 1, j, k + 1) or dfs(i, j + 1, k + 1) or dfs(i, j - 1, k + 1)
            board[i][j] = word[k]
            return res
            
    #遍历i,j,找到word[0]
        for i in range(len(board)):
            for j in range(len(board[0])):
                if dfs(i, j, 0): #当前在board[i][j],单词在word[k]
                    return True
        return False

131.分割回文串

python 复制代码
class Solution:
    def partition(self, s: str) -> List[List[str]]:
        res =[]
        self.backtracking(s, 0, [], res)
        return res
    
    def backtracking(self, s, startindex, path, res):
        if startindex == len(s):
            res.append(path[:])
            return
        
        for i in range(startindex, len(s)):
            ss = s[startindex:i+1]
            if ss == ss[::-1]:   #是回文, 再递归
                path.append(ss)
                self.backtracking(s, i+1, path, res )
                path.pop()

51. N 皇后




棋盘的宽度就是for循环的长度,递归的深度就是棋盘的高度,这样就可以套进回溯法的模板里了。

python 复制代码
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  # 当前位置合法
相关推荐
ALISHENGYA4 分钟前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法
guogaocai1236 分钟前
连续自成核退火热分级(SSA)技术表征共聚聚丙烯(PP)分子链结构
算法
DARLING Zero two♡30 分钟前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
游是水里的游1 小时前
【算法day19】回溯:分割与子集问题
算法
不想当程序猿_1 小时前
【蓝桥杯每日一题】分糖果——DFS
c++·算法·蓝桥杯·深度优先
南城花随雪。2 小时前
单片机:实现FFT快速傅里叶变换算法(附带源码)
单片机·嵌入式硬件·算法
dundunmm2 小时前
机器学习之scikit-learn(简称 sklearn)
python·算法·机器学习·scikit-learn·sklearn·分类算法
古希腊掌管学习的神2 小时前
[机器学习]sklearn入门指南(1)
人工智能·python·算法·机器学习·sklearn
波音彬要多做2 小时前
41 stack类与queue类
开发语言·数据结构·c++·学习·算法
程序员老冯头4 小时前
第十五章 C++ 数组
开发语言·c++·算法