排列是整个数组遍历,组合是从该下标开始遍历后续数据,去重:先排序,然后有相同元素,若前面的元素未使用则给元素也不用,否则会产生重复解,可以借助used数组记录该下标对应的元素是否使用过了。
目录
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