思路:首先,很容易想到直接排序。但是排序复杂度那么高,排序是不可能排序的。这一看O(N)就能解决。简便的方法是用桶排序,由于是曼哈顿距离,比较好枚举。如果是几何距离的话,放到字典中还需要给字典的键排序,复杂度可能又要到O(NlogN)了。
解法一:桶排序
正规的桶排序是记录每个节点的位置,在以位置为下标的数组中记录。咱们的原理是一样的,只是可能每个桶有多个点。判断下最大距离,超出字典范围终止掉就好。
class Solution:
def allCellsDistOrder(self, R: int, C: int, r0: int, c0: int) -> List[List[int]]:
def get_dis(p1, p2):
return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
d = {}
for r in range(R):
for c in range(C):
dis = get_dis((r,c), (r0, c0))
if dis in d:
d[dis].append([r, c])
else:
d[dis] = [[r, c]]
print(d)
l = []
max_dis = R+C-2
for i in range(max_dis+1):
if i not in d:
break
l.extend(d[i])
return l
解法二:BFS
这题一开始拿到手是想着bfs的,但实在不知道咋弄,但一看这个图就懂了,直接BFS就行,这就是曼哈顿距离的魅力。
from queue import Queue
class Solution:
def allCellsDistOrder(self, R: int, C: int, r0: int, c0: int) -> List[List[int]]:
def out_of_range(r, c):
if r < 0 or r >= R or c < 0 or c >= C:
return 1
return 0
def bfs(r, c, l, traversed):
q = Queue()
q.put((r,c))
traversed[r][c] = 1
while not q.empty():
(r, c) = q.get()
if not out_of_range(r+1, c) and not traversed[r+1][c]:
q.put((r+1, c))
traversed[r+1][c] = 1
if not out_of_range(r-1, c) and not traversed[r-1][c]:
q.put((r-1, c))
traversed[r-1][c] = 1
if not out_of_range(r, c+1) and not traversed[r][c+1]:
q.put((r, c+1))
traversed[r][c+1] = 1
if not out_of_range(r, c-1) and not traversed[r][c-1]:
q.put((r, c-1))
traversed[r][c-1] = 1
l.append([r, c])
l, traversed = [], [[0 for _ in range(C)] for _ in range(R)]
bfs(r0, c0, l, traversed)
return l
注意,可以用一个二维数组代替字典存遍历过的路径
解法三:找规律(几何法)
建模较困难,跟BFS一样的原理