classSolution: deflastVisitedCell(self, grid: list[list[str]]) -> list[int]: arrlist = [] r = c = 0 arrlist.append([0, 0]) # 直接按照题意做 whileTrue: ret = [r, c] match grid[r][c]: case"R": c += 1 case"L": c -= 1 case"U": r -= 1 case"D": r += 1 if ( [r, c] in arrlist # 注意这一句 or r == len(grid) or c == len(grid[0]) or r < 0 or c < 0 ): return ret arrlist.append([r, c])
解法没有问题,但是超时了。这是为什么?
请看 if [r, c] in arrlist or ... 中的 arrlist,这是一个列表,而 Python 在执行代码的时候会遍历列表逐个进行比较,而题目给定的数据太大,导致出现 O(n2) 的时间复杂度。
同时请注意 if [r, c] in arrlist or r == len(grid) or ...,如果下一步其实越界了,但还没访问过,那么程序会先把很长的 arrlist 扫一遍,才发现越界。更合理的顺序是先判断边界,再判断是否访问过。不过即使如此,整体的时间复杂度还是下不去。我们需要考虑一种更简单的方案。
classSolution: deflastVisitedCell(self, grid: list[list[str]]) -> list[int]: arrset = set() # list 太复杂了,使用 set r = c = 0 arrset.add((0,0)) # 直接按照题意做 whileTrue: ret = [r, c] match grid[r][c]: case"R": c += 1 case"L": c -= 1 case"U": r -= 1 case"D": r += 1 if ( (r,c) in arrset or r == len(grid) or c == len(grid[0]) or r < 0 or c < 0 ): return ret arrset.add((r,c))
改成这个之后,就能成功通过了。不过我们并没有对源代码进行较大的改动,在这里为什么 Set 就能比 List 更好?为什么我们在这里使用 Turple 而不是 List?
因为 Set 是基于哈希表的实现,如果我们使用 Set 就可以让查重变成 O(1) 的操作,就可以成功通过了。哈希表的前提是里面的元素是“可哈希”的,这个概念有点抽象,我们可以暂且理解为“不可变”。Turple 是不可变的,而 List 是可变的,因此我们就可以用 Turple 代替 List 完成整个操作。