代码随想录算法训练营第三十天| LeetCode332.重新安排行程、LeetCode51. N皇后、LeetCode37. 解数独

332.重新安排行程

题目描述: 332.重新安排行程.

解法

回溯
class Solution(object):
    def backtrack(self,path,start):
        if len(path) == len(self.tickets)+1:
            self.res = path[:]
            return True
            #self.res.append()
        for i,ticket in enumerate(self.tickets):
            if not self.used[i] and ticket[0] == start:
                path.append(ticket[1])
                self.used[i] = True
                state = self.backtrack(path,ticket[1])
                self.used[i] = False
                path.pop()
                if state:
                    return True
    def findItinerary(self, tickets):
        self.tickets = tickets
        self.tickets.sort()
        self.used = [False] * len(self.tickets)
        self.res = None

        self.backtrack(["JFK"],"JFK")
        return self.res

本体相对来说比较简单,首先是可以限定出发点,也就是path的头确定了,然后只需要加入一个used数组,就知道这张票有没有用过了。
需要注意的点是,path长度应该是票数+1。
此外就是为了能保证输出的是最小路径,其实可以上来先进行排序,这样就能保证第一个遍历到的完整路径一定是最小路径。
还有一个需要注意的点是,为了能直接返回第一个遍历成功的路径,可以设定一个True返回值,然后在每次回溯结束之后进行判断,若是True就返回上一层。

51. N皇后

题目描述: 51. N皇后.

解法

回溯
class Solution(object):
    def check(self,floor,i):
        p = floor-1
        q = i - 1
        while p>=0 and q>=0:
            if self.chessboard[p][q] == 'Q':
                return False
            p-=1
            q-=1
        p = floor - 1
        q = i+1
        while p>=0 and q < self.length:
            if self.chessboard[p][q] == 'Q':
                return False
            p-=1
            q+=1
        return True
    def backtrack(self,floor):

        if floor == self.length:
            self.res.append(self.chessboard[:])
            return
        for i in range(self.length):
            if self.used[i] or not self.check(floor,i):
                continue
            self.used[i] = True
            self.chessboard[floor] = self.chessboard[floor][:i] + 'Q' + self.chessboard[floor][i+1:]
            self.backtrack(floor+1)
            self.chessboard[floor] = self.chessboard[floor][:i] + '.' + self.chessboard[floor][i+1:]
            self.used[i] = False
            
    def solveNQueens(self, n):
        self.length = n
        self.chessboard = ['.' * n for _ in range(n)]
        self.used = [False] * n
        self.res = []
        self.backtrack(0)
        return self.res

整体思路并不难,主要的问题就在
1.如何设计棋盘
使用二维数组即可
2.如何判定上下还有倾斜的问题
在每一层回溯中,可以保证同一层不会出现重复,使用used数组可以保证一列不会出现重复。
倾斜的话就考虑当前的位置在哪,然后往左上和右上循环即可,因为当前点的下层还没插入,所以不需要考虑往左下和右下的问题
3.如何修改棋盘
由于是str类型,所以不能直接使用索引进行修改,只能是通过切片的方式。

37. 解数独

题目描述: 37. 解数独.

解法

回溯
class Solution(object):
    def vaild(self,i,j,k,board):
        for p in range(len(board)):
            if board[p][j] == str(k):
                return False
            if board[i][p] == str(k):
                return False
        p_start = (i//3) * 3
        q_start = (j//3) * 3
        for p in range(p_start,p_start+3):
            for q in range(q_start,q_start+3):
                if board[p][q] == str(k):
                    return False
        return True
    
    def backtrack(self,board):
        for i in range(9):
            for j in range(9):
                if board[i][j] != '.':
                    continue
                for k in range(1,10):
                    if self.vaild(i,j,k,board):
                        board[i][j] = str(k)
                        if self.backtrack(board):
                            return True
                        board[i][j] = '.'
                return False
        return True

    def solveSudoku(self, board):
        self.backtrack(board)

思路就是在一个棋盘上的每一个点进行回溯,不要想象成一个二维的期盼,把它想象成一个长数组,需要我们去填空,然后每一个空都可能是1-9,每一个空进行一次回溯,如果到了最后一个空返回的是True,就一层一层向上,如果某个位置1-9都不合适,就可以从这个回溯中出去了,要回到上一层重新进行回溯。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值