1. 程式人生 > >LeetCode廣度優先演算法的題

LeetCode廣度優先演算法的題

真的坑,自己想完全沒想到,看了一些大神的部落格寫出來的。那個列表很坑,不能寫在一起。
但作為一名小白還是很欣慰的。

'''
給定一個由 ‘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)