矩陣中的路徑 機械人的運動範圍題目分析

2021-10-23 03:41:22 字數 3842 閱讀 1957

「矩陣中的路徑」 和 "機械人的運動範圍"是劍指offer的倒數第2,3道題目,因為這兩道題思路類似,就放在一起說。

請設計乙個函式,用來判斷在乙個矩陣中是否存在一條包含某字串所有字元的路徑。路徑可以從矩陣中的任意一格開始,每一步可以在矩陣中向左、右、上、下移動一格。如果一條路徑經過了矩陣的某一格,那麼該路徑不能再次進入該格仔。例如,在下面的3×4的矩陣中包含一條字串「bfce」的路徑(路徑中的字母用加粗標出)。

[[「a」,「b」,「c」,「e」],

[「s」,「f」,「c」,「s」],

[「a」,「d」,「e」,「e」]]

但矩陣中不包含字串「abfb」的路徑,因為字串的第乙個字元b佔據了矩陣中的第一行第二個格仔之後,路徑不能再次進入這個格仔。

示例 1:

輸入:board = [[「a」,「b」,「c」,「e」],[「s」,「f」,「c」,「s」],[「a」,「d」,「e」,「e」]], word = 「abcced」

輸出:true

解題思路:

這個題是路徑規劃問題,給定乙個矩陣地圖和一條路,判斷這個地圖裡面是否存在一條路徑和題目所給這條路完全匹配

既然是路徑規劃,很容易想到用到遞迴+回溯,因為每個矩陣中的每個格仔可能被多條不同的路徑經過,所以每條路徑用完這個格仔之後要將其復原,因此需要乙個二維bool型陣列,來標記格仔是否被走過,這是回溯法的常規套路

有了上面的思路,我們就來進行匹配。題目給定乙個字串word,那我們就從矩陣的第乙個位置( board[0][0] )開始匹配,每次走完乙個字元,下乙個字元我們有四種選擇:往上,往下,往左,往右。

所以遞迴主體就要包含這四種情況,但是別忘了上面說的,走乙個字元就要做乙個標記,也即是二維陣列的該位置標記,遞迴完後進行復原,給其他路徑去用

那遞迴主體確定了之後,就要進行邊界判斷,因為遞迴也就包含兩部分:邊界+主體。那邊界就很簡單了,既然上面分析了乙個字元有四種走法,那肯定不能跑出界,也不能有小於0的情況,並且!每個路徑用過的格仔 本路徑不能再用,也即是每個格仔在每條路徑中只能用一次(這是題目條件)。

因此,總結一下邊界條件:① 越界 ② 走過的格仔不能再走 ③匹配過程中某個值不相等,那就直接return false。

如果上面的情況都沒有發生,那就說明匹配過程很順利,直接走完題目所給的路徑,那麼return true。

下面開始寫**:用乙個變數index跟蹤題目所給的路徑,逐個字元匹配,當index = word.length( )時,return true;

class

solution

vector

bool

>>

vis(board.

size()

, vector<

bool

>

(board[0]

.size()

,false))

;//標記陣列

for(

int i =

0; i < board.

size()

;++i)}}

return

false;}

bool

dfs(vector

char

>>

&board, string &word,

int x,

int y,

int index, vector

bool

>>

&vis)

if(x <

0|| x >= board.

size()

|| y <

0|| y >= board[0]

.size()

|| vis[x]

[y])

if(board[x]

[y]!= word[index]

)//下面是遞迴+回溯,也就是匹配的過程

vis[x]

[y]=

true

;//用了就做標記

bool res =

dfs(board, word, x +

1, y, index +

1, vis)

||dfs

(board, word, x -

1, y, index +

1, vis)

||dfs

(board, word, x, y +

1, index +

1, vis)

||dfs

(board, word, x, y -

1, index +

1, vis)

; vis[x]

[y]=

false

;//復原,給其他路徑用

return res;}}

;

這個思路是比較容易想的,不會太複雜。但是在leetcode中需要注意超時的情況,一開始我傳參的時候,第乙個引數board沒有傳引用,直接傳值,結果一直超時,在時間複雜度較大的時候,一定要盡量優化,傳引用省去了值拷貝的過程,因此可以accept。

地上有乙個m行n列的方格,從座標 [0,0] 到座標 [m-1,n-1] 。乙個機械人從座標 [0, 0] 的格仔開始移動,它每次可以向左、右、上、下移動一格(不能移動到方格外),也不能進入行座標和列座標的數字之和大於k的格仔。例如,當k為18時,機械人能夠進入方格 [35, 37] ,因為3+5+3+7=18。但它不能進入方格 [35, 38],因為3+5+3+8=19。請問該機械人能夠到達多少個格仔?

示例 1:

輸入:m = 2, n = 3, k = 1

輸出:3

示例 2:

輸入:m = 3, n = 1, k = 0

輸出:1

解題思路:

這個題和上乙個「矩陣中的路徑」比較類似,最重要的不同點是上乙個題是典型的路徑規劃問題,需要用到回溯法(因為可能多條路徑經過同乙個點),但是這個題不一樣,他要的是我們去判斷每乙個點是不是滿足條件(和class

solution

intcalculate

(int x)

return sum;

}void

dfs(

int m,

int n,

int k,

int x,

int y, vector

bool

>>

&vis)if(

calculate

(x)+

calculate

(y)> k)

vis[x]

[y]=

true

;//做標記

++sum;

//可用格仔+1

dfs(m, n, k, x +

1, y, vis)

;//往下

dfs(m, n, k, x -

1, y, vis)

;//往上

dfs(m, n, k, x, y +

1, vis)

;//往右

dfs(m, n, k, x, y -

1, vis)

;//往左

回溯法 矩陣中的路徑,機械人的運動範圍

回溯法是做了剪枝改進的窮舉法,適合由多個步驟組成,並且每個步驟都有多個選項組成的問題。回溯法的解空間樹到達葉結點時,如果在葉子結點的狀態滿足題目的約束條件,那麼就找到了乙個可行的解決方案。回溯二字在於,如果在解空間樹上的某個結點不滿足約束條件,那麼就退回到上一結點,再嘗試其它選項 如果全部試過都不行...

程式設計題 機械人的運動範圍

地上有乙個m行和n列的方格。乙個機械人從座標 0,0 的格仔開始移動,每一次只能向左,右,上,下四個方向中其中乙個方向移動一格,但是不能進入行座標和列座標的數字之和大於k的格仔。例如,當k為18時,機械人能夠進入方格 35,37 因為3 5 3 7 18。但是,它不能進入方格 35,38 因為3 5...

演算法題 機械人的運動範圍

題目描述 地上有乙個m行和n列的方格。乙個機械人從座標0,0的格仔開始移動,每一次只能向左,右,上,下四個方向移動一格,但是不能進入行座標和列座標的數字之和大於k的格仔。例如,當k為18時,機械人能夠進入方格 35,37 因為3 5 3 7 18。但是,它不能進入方格 35,38 因為3 5 3 8...