LeetCode廣度優先演算法的題
阿新 • • 發佈:2018-12-26
真的坑,自己想完全沒想到,看了一些大神的部落格寫出來的。那個列表很坑,不能寫在一起。
但作為一名小白還是很欣慰的。
'''
給定一個由 ‘1’(陸地)和 ‘0’(水)組成的的二維網格,計算島嶼的數量。
一個島被水包圍,並且它是通過水平方向或垂直方向上相鄰的陸地連線而成的。
你可以假設網格的四個邊均被水包圍
'''
# 考慮這個題目,計算島嶼數量,也就是單獨島嶼的數量,
# 兩個以上的1 連在一起的算是一個島嶼,那麼也就是隻要找到單獨一塊的島嶼就行了,
# 這樣就很好理解了!
lt1 = [
[1, 1, 0, 0, 0],
[0, 1, 0, 0, 1],
[0, 0, 0, 1, 1 ],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 1]
]
lt2 = [
[1, 1, 1, 1, 0],
[1, 1, 0, 1, 0],
[0, 0, 0, 1, 1],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 1]
]
class Solution:
def munIsLand(self, grid):
n = len(grid)
if n == 0:
return '地圖為空'
m = len(grid[0])
if m == 0:
return '地圖為空'
# 當找到島嶼的時候就把下面變數自+1
res = 0
# 開始遍歷尋找第一個 1 ,(島嶼)
for i in range(n):
for j in range(m):
# 判斷是不是一個島嶼
if grid[i][j] == 1:
res = res + 1
# 這個時候還要判斷與它連線在一起的1,
# 畢竟一家人要整整齊齊的,所以遞迴尋找連在一起的所有島嶼,
# 同時需要注意的是,一個島嶼你只能遍歷一次,
# 所以打個標識,讓尋找到的島嶼變成0
self.change(grid, i, j)
return res
def change(self, grid, i, j):
grid[i][j] = 0
# 判斷這個島嶼上下左右的方向
# 判斷上方字元
if i > 0 and grid[i - 1][j] == 1:
self.change(grid, i - 1, j)
# 判斷左方字元
if j > 0 and grid[i][j - 1] == 1:
self.change(grid, i, j - 1)
# 判斷下方字元
if i < len(grid) - 1 and grid[i + 1][j] == 1:
self.change(grid, i + 1, j)
# 判斷右方字元
if j < len(grid[0]) - 1 and grid[i][j + 1] == 1:
self.change(grid, i, j + 1)
ss = Solution()
print(ss.munIsLand(lt1))
print(ss.munIsLand(lt2))
- 關於密碼鎖問題
import collections
class Solution:
'''
演算法思想:
這也是一道很有意思的題,其實本質就是個迷宮遍歷的問題,只不過相鄰位置不再是上下左右四個位置,
而是四位數字每個都加一減一,總共有八個相鄰的位置。與經典BFS遍歷迷宮解法唯一不同的就是找下一個位置的地方,
這裡我們要遍歷四位數字的每一位,然後分別加1減1,我們用j從-1遍歷到1,遇到0跳過,也就是實現了加1減1的過程。
然後我們要計算要更新位上的數字,為了處理9加1變0,和0減1變9的情況,我們統一給該位數字加上個10,然後再加或減1,
最後再對10取餘即可。
如果此時新生成的字串等於target了,直接返回結果res,否則我們看如果該字串不在死鎖集合裡,
且之前沒有遍歷過,那麼加入佇列queue中,之後將該字串加入visited集合中即可。注意這裡在while迴圈中,
由於要一層一層的往外擴充套件
'''
def openLock(self, deadends, target):
deadset = set(deadends)
if (target in deadset) or ("0000" in deadset):
return -1
# 之前沒有遍歷過加入佇列之中
que = collections.deque()
que.append("0000")
# 然後在把他加入集合裡面
visited = set(["0000"])
step = 0
# 這個要一層層的向外擴張
while que:
# 每次迴圈尋找次數都會+1
step += 1
# 計算每次迴圈時,佇列中原書的個數
size = len(que)
# 在新的元素基礎上開始遍歷
for i in range(size):
# 依次取出 0 1 2 3 4 ... 賦值給point指標
point = que.popleft()
# 第二次迴圈,給每個滾輪上面操作
for j in range(4):
# 第三次迴圈,設定 +1, -1,讓每個滾輪加+、減一
for k in range(-1, 2, 2):
# 程式執行到這裡,point已經執行完畢了,也就是point就等於queue,這裡是把point賦給newPoint
newPoint = [i for i in point]
# 讓這個新賦值的佇列中,給每個元素加減1操作,並且這裡有-1-9,10-0的轉換操作
newPoint[j] = chr((ord(newPoint[j]) - ord('0') + k) % 10 + ord('0'))
# 這裡把列表裡面['1','2','3','4']轉換為'1234'
newPoint = "".join(newPoint)
# 判斷這個字串是不是目標字串
if newPoint == target:
return step
# 如果這個字串不再死鎖或者集合字串中, 就跳過這次迴圈
if (newPoint in deadset) or (newPoint in visited):
continue
# 把這個字串加入到佇列queue中
que.append(newPoint)
# 把這個字串加入到集合中
visited.add(newPoint)
return -1
a = Solution()
ret = a.openLock('1515', '1523')
print(ret)