代码随想录算法训练营第三十天| 332.重新安排行程(跳过)、51. N皇后 、37. 解数独

Leetcode - 51

首先这道题不同于以往的是,这是处理一个二维序列,前面我们都处理的是一维的,那么二维序列的话我们就要用两个for吗?其实这里不用,因为在每一行里,我们只要找到一个适合的位置放入皇后就可以直接continue到下一行了,所以说这里for循环只要一个,且这个for循环对应的是列数,行数我们用row来记录,在某一行找到合适位置后,就row+1传递都下一个递归当中。

关于终止条件,这里是row到最后一行n-1并完成处理后,也就是递归传递到下一层,此时row==n,这就是终止条件,此时我们收集结果。

关于位置是否合适,我们通过当前位置的同列上方元素,左上方对角线上元素,右上方对角线上元素来判断是否有皇后,没有皇后就表示位置合理。

def solveNQueens(self, n: int) -> List[List[str]]:
 
        source = [["." for _ in range(n)] for _ in range(n)]
        res = []

        def process(board,row, col):
            #判断同一列是否冲突
            for i in range(len(board)):
                if board[i][col] == 'Q':
                    return False
            # 判断左上角是否冲突
            i = row -1
            j = col -1
            while i>=0 and j>=0:
                if board[i][j] == 'Q':
                    return False
                i -= 1
                j -= 1
            # 判断右上角是否冲突
            i = row - 1
            j = col + 1
            while i>=0 and j < len(board):
                if board[i][j] == 'Q':
                    return False
                i -= 1
                j += 1
            return True

        def backTraking(raw,temp):
            nonlocal res
            if raw == n:
                t = []
                for line in temp:
                    t.append("".join(line))
                
                res.append(t[:])
                return 

            for i in range(n):
                if not process(temp,raw,i):
                    continue
                
                
                temp[raw][i] = "Q"
                backTraking(raw +1,temp)
                temp[raw][i] = "."

        backTraking(0,source)
        return res

Leetcode - 37

这题比N皇后还要难,这里是一行要可能填充多个元素,也是一个二维数据,所以这里我们并不能像N皇后那里使用row来避免两重循环了,这里外层循环代表行,内层循环代表列,注意此题只需要我们找到一个答案并填充即可,所以这里我们并不需要写终止条件,此处我们是仅需要在单个树枝上收集结果而不是像前面的回溯题一样在所有树枝上收集,这里是需要返回值的,通过返回值来标识什么时候可以终止递归

在棋盘中,一旦我们遇到值为“.”的元素,我们就开始从1~9中一一试值,这里判断值是否可以放入,我们需要单独写一个函数,三个点:1。 不能与同行元素重复 2. 不能与同列元素重复, 3. 不能在所处的3 * 3方阵中元素重复。不符合就continue,直到符合。符合 就赋值,然后进入下一次递归,递归有返回值,若为True则直接return 递归后依旧是将元素从数值还原成"."。

若在1-9中找不到元素,则返回False。

两次for循环结束后返回True,代表如果中间一直顺畅,每个位置都有合适的值放入,则完成

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

        def getCurrPos(raw,col):
            aSet = set()
            if raw <=2:
                a = board[:3]
                
            elif raw > 2 and raw <=5:
                a = board[3:6]
            
            else:
                a = board[6:]
            
            if col <=2:
                a = [line[:3] for line in a]
                    
            elif col >2 and col <=5:
                a = [line[3:6] for line in a]
            
            else:
                a = [line[6:] for line in a]

            for line in a:
                for item in line:
                    aSet.add(item) 
            return aSet


        def isValid(value,raw,col):
            zong = [board[r][col] for r in range(9)]
            if (value in board[raw]) or (value in zong) or (value in getCurrPos(raw,col)):
                return False
            return True

        def backTracking():
            nonlocal board
            for i in range(9):
                for j in range(9):
                    if board[i][j] == ".":
                        for v in range(1,10):
                            if not isValid(str(v),i,j):
                                continue
                            else:
                                board[i][j] = str(v)
                                if backTracking():
                                    return True
                                board[i][j] = "."
                        else:
                            return False

            return True

        backTracking()

        return board
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值