您當前的位置:首頁 > 攝影

LeetCode-79 單詞搜尋☆中等,偏移量技巧

作者:由 xndgevr 發表于 攝影時間:2019-11-23

題目:給定一個二維網格和一個單詞,找出該單詞是否存在於網格中。

單詞必須按照字母順序,透過相鄰的單元格內的字母構成,其中“相鄰”單元格是那些水平相鄰或垂直相鄰的單元格。同一個單元格內的字母不允許被重複使用。

示例:

board =

[‘A’,‘B’,‘C’,‘E’],

[‘S’,‘F’,‘C’,‘S’],

[‘A’,‘D’,‘E’,‘E’]

給定 word = “ABCCED”, 返回 true。

給定 word = “SEE”, 返回 true。

給定 word = “ABCB”, 返回 false。

思路:這題想到要用遞迴,但難點在於下一層遞迴的四個方向的座標計算、狀態的重置、以及如何回溯、如何判斷是否找到這4個條件。

#這是自己第一遍寫得程式碼,存在很多冗餘,比如遞迴結束的條件、formed的使用、上下左右的座標計算方法、

#狀態重置的寫法等,最後執行超時

class

Solution

def

exist

self

board

List

List

str

]],

word

str

->

bool

row

=

len

board

if

row

==

0

return

False

column

=

len

board

0

])

if

column

==

0

return

False

l_word

=

len

word

if

l_word

==

0

or

l_word

>

row

*

column

return

False

used

=

[[

0

for

j

in

range

column

)]

for

i

in

range

row

)]

start

=

[]

#先找到可以匹配的起點

for

i

in

range

row

):

for

j

in

range

column

):

if

board

i

][

j

==

word

0

]:

start

append

([

i

j

])

def

search

start

formed

word

l

used

res

):

# flag = False

if

len

formed

[:])

==

l

# print(formed)

res

append

formed

return

if

len

word

==

0

return

around_first

=

[[

max

start

0

-

1

0

),

start

1

]],

start

0

],

min

start

1

+

1

column

-

1

)],

min

start

0

+

1

row

-

1

),

start

1

]],

start

0

],

max

start

1

-

1

0

)]]

#上、右、下、左

around_first

=

item

for

item

in

around_first

if

item

!=

start

and

not

used

item

0

]][

item

1

]]]

for

i

in

around_first

# print(i)

if

board

i

0

]][

i

1

]]

==

word

0

]:

used

i

0

]][

i

1

]]

=

1

formed

append

word

0

])

search

i

formed

word

1

:],

l

used

res

# if search(i, formed, word[1:], l, used, flag):flag = True

formed

pop

()

used

start

0

]][

start

1

]]

=

0

res

=

[]

for

first

in

start

formed

=

word

0

]]

used

first

0

]][

first

1

]]

=

1

search

first

formed

word

1

:],

l_word

used

res

if

len

res

>

0

return

True

#判斷是否成功的條件太麻煩

used

=

[[

0

for

j

in

range

column

)]

for

i

in

range

row

)]

#該步完全多餘

return

False

對比liweiwei1419的如下程式碼:

from

typing

import

List

class

Solution

# (x-1,y)

# (x,y-1) (x,y) (x,y+1)

# (x+1,y)

directions

=

[(

0

-

1

),

-

1

0

),

0

1

),

1

0

)]

def

exist

self

board

List

List

str

]],

word

str

->

bool

m

=

len

board

if

m

==

0

return

False

n

=

len

board

0

])

marked

=

[[

False

for

_

in

range

n

)]

for

_

in

range

m

)]

for

i

in

range

m

):

for

j

in

range

n

):

# 對每一個格子都從頭開始搜尋

if

self

__search_word

board

word

0

i

j

marked

m

n

):

return

True

return

False

def

__search_word

self

board

word

index

start_x

start_y

marked

m

n

):

# 先寫遞迴終止條件

if

index

==

len

word

-

1

return

board

start_x

][

start_y

==

word

index

# 中間匹配了,再繼續搜尋

if

board

start_x

][

start_y

==

word

index

]:

# 先佔住這個位置,搜尋不成功的話,要釋放掉

marked

start_x

][

start_y

=

True

for

direction

in

self

directions

new_x

=

start_x

+

direction

0

new_y

=

start_y

+

direction

1

# 注意:如果這一次 search word 成功的話,就返回

if

0

<=

new_x

<

m

and

0

<=

new_y

<

n

and

\

not

marked

new_x

][

new_y

and

\

self

__search_word

board

word

index

+

1

new_x

new_y

marked

m

n

):

return

True

marked

start_x

][

start_y

=

False

return

False

將自己的程式碼修改之後:

class

Solution

def

exist

self

board

List

List

str

]],

word

str

->

bool

row

=

len

board

if

row

==

0

return

False

column

=

len

board

0

])

if

column

==

0

return

False

used

=

[[

0

for

j

in

range

column

)]

for

i

in

range

row

)]

def

search

start

word

board

used

):

#偏移量陣列,在二維平面內經常使用的技巧

directions

=

[(

-

1

0

),(

0

1

),(

1

0

),(

0

-

1

)]

#終止條件寫成這樣是避免Word中僅有一個字元

if

len

word

==

1

return

board

start

0

]][

start

1

]]

==

word

0

if

board

start

0

]][

start

1

]]

==

word

0

]:

used

start

0

]][

start

1

]]

=

1

for

i

in

directions

new_x

=

start

0

+

i

0

new_y

=

start

1

+

i

1

#此處的遞迴形式寫得很好,將遞迴作為條件之一,得到返回

if

0

<=

new_x

<

row

and

0

<=

new_y

<

column

and

not

used

new_x

][

new_y

and

\

search

((

new_x

new_y

),

word

1

:],

board

used

):

return

True

#狀態重置,如果沒有下一匹配的字元,將釋放當前的字元佔用,即為回溯

used

start

0

]][

start

1

]]

=

0

return

False

for

i

in

range

row

):

for

j

in

range

column

):

if

search

((

i

j

),

word

board

used

):

return

True

return

False

已經戰勝

73。85

%

python3

提交記錄

作者的程式碼直接

暴力遍歷,就開始匹配

比如:先找出可以匹配的起點位置。可以提升一點T(O)

說明:

1、偏移量陣列在二維平面內是經常使用的,可以把它的設定當做一個技巧,並且在這個問題中,偏移量陣列內的 4 個偏移的順序無關緊要;

說明:類似使用這個技巧的問題還有:

「力扣」第 130 題:被圍繞的區域

「力扣」第 200 題:島嶼數量

2、對於這種搜尋演算法,我認為理解 DFS 和狀態重置並不難,程式碼編寫也相對固定,難在程式碼的編寫和細節的處理,建議多次編寫,自己多總結多思考,把自己遇到的坑記下。

標簽: word  start  board  NEW  used