leetcode 回溯(三)

排列是整個數組遍歷,組合是從該下標開始遍歷後續數據,去重:先排序,然後有相同元素,若前面的元素未使用則給元素也不用,否則會產生重複解,可以藉助used數組記錄該下標對應的元素是否使用過了。

目錄

1034. 邊框着色

417. 太平洋大西洋水流問題

51. N皇后


1034. 邊框着色

https://leetcode-cn.com/problems/coloring-a-border/

給出一個二維整數網格 grid,網格中的每個值表示該位置處的網格塊的顏色。只有當兩個網格塊的顏色相同,而且在四個方向中任意一個方向上相鄰時,它們屬於同一連通分量。連通分量的邊界是指連通分量中的所有與不在分量中的正方形相鄰(四個方向上)的所有正方形,或者在網格的邊界上(第一行/列或最後一行/列)的所有正方形。給出位於 (r0, c0) 的網格塊和顏色 color,使用指定顏色 color 爲所給網格塊的連通分量的邊界進行着色,並返回最終的網格 grid 。

示例 1:輸入:grid = [[1,1],[1,2]], r0 = 0, c0 = 0, color = 3,輸出:[[3, 3], [3, 2]]
示例 2:輸入:grid = [[1,2,2],[2,3,2]], r0 = 0, c0 = 1, color = 3,輸出:[[1, 3, 3], [2, 3, 3]]
示例 3:輸入:grid = [[1,1,1],[1,1,1],[1,1,1]], r0 = 1, c0 = 1, color = 2,輸出:[[2, 2, 2], [2, 1, 2], [2, 2, 2]]
提示:1 <= grid.length <= 50,1 <= grid[0].length <= 50,1 <= grid[i][j] <= 1000,0 <= r0 < grid.length,0 <= c0 < grid[0].length,1 <= color <= 1000

題解

一:注意與733. 圖像渲染的區別,733是連通分量重的所有值均替換成新值,所以可以不用used標記,直接修改,修改過了即遍歷過了。這邊借鑑463. 島嶼的周長的法二,DFS求解。在遇到上下左右邊界且值爲oldColor時替換成新值。這邊我們注意used的賦值,只有訪問到且值爲oldColor時才標記,733不用標記,是因爲值的修改,每個oldColor的值都會修改,就不用額外標記,而這邊不是所有的值都會修改(只會修改邊界以及和別的顏色的區別處)。借鑑463. 島嶼的周長,對別的顏色分解處修改,所以得放在循環裏面。463題無所謂放在哪,因爲不需要準確的位置,只需要計數就可。

class Solution(object):
    def colorBorder(self, grid, r0, c0, color):
        """
        :type grid: List[List[int]]
        :type r0: int
        :type c0: int
        :type color: int
        :rtype: List[List[int]]
        """
        def DFS(x, y, oldColor, color):
            if (x < 0 or x >= len(image) or y < 0 or y>= len(image[0])) or used[x][y]:
               return 
            if image[x][y] == oldColor:
                used[x][y] = True
            if ((x == 0 or x == len(image) - 1 
                or y == 0 or y == len(image[0]) - 1) and image[x][y] == oldColor):
                image[x][y] = color

            for p in pos:
                t_x = x + p[0]
                t_y = y + p[1]
                if (t_x < 0 or t_x >= len(image) or t_y < 0 or t_y >= len(image[0])):
                    continue
                if image[t_x][t_y] != oldColor and not used[t_x][t_y]:
                    image[x][y] = color
                    continue
                DFS(t_x, t_y, oldColor, color)

        m, n = len(grid), len(grid[0])
        oldColor = grid[r0][c0]
        image = [[grid[i][j] for j in xrange(n)] for i in xrange(m)]
        if oldColor == color:
            return image

        pos = [[0, 1], [1, 0], [0, -1], [-1, 0]] 
        used = [[False] * n for _ in xrange(m)]
        
        DFS(r0, c0, oldColor, color)

        return image

417. 太平洋大西洋水流問題

https://leetcode-cn.com/problems/pacific-atlantic-water-flow/

給定一個 m x n 的非負整數矩陣來表示一片大陸上各個單元格的高度。“太平洋”處於大陸的左邊界和上邊界,而“大西洋”處於大陸的右邊界和下邊界。規定水流只能按照上、下、左、右四個方向流動,且只能從高到低或者在同等高度上流動。請找出那些水流既可以流動到“太平洋”,又能流動到“大西洋”的陸地單元的座標。

提示:輸出座標的順序不重要,m 和 n 都小於150
示例:給定下面的 5x5 矩陣:

  太平洋 ~   ~   ~   ~   ~ 
       ~  1   2   2   3  (5) *
       ~  3   2   3  (4) (4) *
       ~  2   4  (5)  3   1  *
       ~ (6) (7)  1   4   5  *
       ~ (5)  1   1   2   4  *
          *   *   *   *   * 大西洋

返回:[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (上圖中帶括號的單元).

題解

一:從邊界開始反推,反推人往高處走,每次都走向更高的海拔或者在同海拔間移動。感覺這樣編程比水往低處流的正向思考更容易些。

class Solution(object):
    def pacificAtlantic(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[List[int]]
        """
        def DFS(x, y, visited):
            if (x < 0 or x >= len(matrix) or y < 0 or y >= len(matrix[0])):
                return 
            visited[x][y] = True

            for p in pos:
                t_x = x + p[0]
                t_y = y + p[1]
                if (t_x < 0 or t_x >= len(matrix) or t_y < 0 or t_y >= len(matrix[0])
                   or visited[t_x][t_y] or matrix[x][y] > matrix[t_x][t_y]):
                    continue
                DFS(t_x, t_y, visited)
            
        if not matrix or not matrix[0]:
            return []
        
        # Pacific 大西洋 Atlantic 太平洋
        m, n = len(matrix), len(matrix[0])
        pos = [[0, 1], [1, 0], [0, -1], [-1, 0]]
        
        visited_Pacific = [[False] * n for _ in xrange(m)]
        for j in xrange(n):
            DFS(0, j, visited_Pacific)
        for i in xrange(m):
            DFS(i, 0, visited_Pacific)

        visited_Atlantic = [[False] * n for _ in xrange(m)]
        for j in xrange(n):
            DFS(m - 1, j, visited_Atlantic)
        for i in xrange(m):
            DFS(i, n - 1, visited_Atlantic)

        res = [[i, j] for i in xrange(m) for j in xrange(n) 
               if visited_Pacific[i][j] and visited_Atlantic[i][j]]
        return res

51. N皇后

n 皇后問題研究的是如何將 n 個皇后放置在 n×n 的棋盤上,並且使皇后彼此之間不能相互攻擊。

上圖爲 8 皇后問題的一種解法。

給定一個整數 n,返回所有不同的 n 皇后問題的解決方案。每一種解法包含一個明確的 n 皇后問題的棋子放置方案,該方案中 'Q' 和 '.' 分別代表了皇后和空位。

示例:輸入: 4
輸出: [
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // 解法 2
  "Q...",
  "...Q",
  ".Q.."]
]
解釋: 4 皇后問題存在兩個不同的解法。
提示:皇后,是國際象棋中的棋子,意味着國王的妻子。皇后只做一件事,那就是“喫子”。當她遇見可以喫的棋子時,就迅速衝上去喫掉棋子。當然,她橫、豎、斜都可走一到七步,可進可退。(引用自 百度百科 - 皇后 )

題解

一:遞歸,每次嘗試在index行放入一個皇后(一行只能放一個),所以若index行的j列放一個皇后不會發生衝突,則下一次index可加1,即狀態會產生改變,若不可以 ,for循環繼續找該行中的後續位置(遞歸狀態不改變,只是for 循環中列的位置向後遍歷),若該行中均沒有可以放置不引起衝突的列,則進行回溯,退回到上一層,遍歷上一層的下一個列位置j。row[i]表示i行的皇后放在row[i]列,這個用來記錄的。還有col,diag1和diag2列表是爲了快速判斷(每列,每個對角線位置)是否會有衝突的。

class Solution(object):
    def solveNQueens(self, n):
        """
        :type n: int
        :rtype: List[List[str]]
        """
        def ping():
            tmp = []
            for i in xrange(n):
                tmp.append('.' * row[i] + 'Q' +'.' * (n - 1 - row[i]))
            res.append(tmp)
        
        # DFS,每次嘗試排列index行的皇后
        def DFS(index, n):
            if index == n:
                ping()
            for j in xrange(n):
                if not col[j] and not diag1[index + j] and not diag2[index - j + (n - 1)]:
                    row[index] = j
                    col[j] = True
                    diag1[index + j] = True
                    diag2[index - j + (n - 1)] = True
                    DFS(index + 1, n)
                    col[j] = False
                    diag1[index + j] = False
                    diag2[index - j + (n - 1)] = False
        
        # 用來記錄,以便快速判斷是否有衝突
        col, diag1, diag2 = [False] * n, [False] * (2 * n + 1), [False] * (2 * n + 1)
        # 用來記錄
        row = [-1] * n

        res = []
        DFS(0, n)
        return res

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章