2020年4月12日 星期日

Leetcode題解 Python:Check if There is a Valid Path in a Grid

給一個二維串列 grid,每格代表一種道路,其值可以對應下表,要回傳是否能從左上角走到右下角。
1 which means a street connecting the left cell and the right cell.
2 which means a street connecting the upper cell and the lower cell.
3 which means a street connecting the left cell and the lower cell.
4 which means a street connecting the right cell and the lower cell.
5 which means a street connecting the left cell and the upper cell.
6 which means a street connecting the right cell and the upper cell.
對於這種地圖或是面積的圖像問題,我總是感到棘手,也許有一套通用思路,不過可能需要很多經驗值累積才能解得順手。

從左上角開始,但是沒有規定左上角一定是從外面延伸進來,如果是 grid[0][0]  == 5,一開始就死局。如果等於 4,那一開始就會有兩條路線。

要怎麼解決起始有兩條路線的問題,就會是一個難題。又或者拋開心中虛擬的小車車,直接用遞迴 + memo 去從(0, 0)拔起所有合格座標,再看看右下角是否存在。

街道有六種形式,而且具有方向問題,困難點在此,要怎麼妥善解決轉向,這就值得思考。


每一種街道只能接受兩種方向,例如 street 1,如果從右邊來,通過後方向朝左邊;如果從左邊來,通過後方向朝右邊。如果從其他方向,那就代表無法接到一起。

街道對應的方向就只能老實打出,無法再快,這是題目的定義。

如果在當前位置向右走,對下一個位置是從左來,對於制定方向前進的人,要留意方向上的切換。

思考一下之後,使用遞迴拔出所有與(0,0)連接的街道會比較泛用。
class Solution:
    def hasValidPath(self, grid):
        """
        1 which means a street connecting the left cell and the right cell.
        2 which means a street connecting the upper cell and the lower cell.
        3 which means a street connecting the left cell and the lower cell.
        4 which means a street connecting the right cell and the lower cell.
        5 which means a street connecting the left cell and the upper cell.
        6 which means a street connecting the right cell and the upper cell.
        """   
        # 0 up 1 left 2 down 3 right        
        streets = {1:(1,3), 2:(0,2), 3:(1,2), 4:(3,2), 5:(1,0), 6:(3,0)}

        path = set()
        rows, cols = len(grid), len(grid[0]) 

        def searchMap(y,x):
            if y < 0 or x < 0: return 
            if y == rows or x == cols: return
            path.add((y,x))
            ds = streets[grid[y][x]]
   
            for d in ds:
                x2,y2=x,y
                if d == 0:                    
                    y2 = y-1
                elif d == 1:
                    x2 = x-1
                elif d == 2:
                    y2 = y+1
                else:
                    x2 = x+1
                d = (d+2)%4 #換方向(下一個位置的相對方向)
                if (y2, x2) not in path:
                    if y2 < 0 or x2 < 0 or y2 == rows or x2 == cols: 
                        continue
                    elif d in streets[grid[y2][x2]]:
                        searchMap(y2,x2)

        searchMap(0,0)
        return (rows-1, cols-1 ) in path