Python数据结构之宽度优先搜索

目录

  1. 岛屿数量 (LeetCode 200)
  2. 词语阶梯(LeetCode 127)
  3. 词语阶梯2 (LeetCode 126)
  4. 01矩阵 (LeetCode 542)
  5. 太平洋与大西洋的水流 (LeetCode 417)
  6. 收集雨水2 (LeetCode 407)

1. 岛屿数量 (LeetCode 200 Number of Islands)

1.1题目

Given a 2d grid map of ‘1’s (land) and ‘0’s (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

Example 1:

11110
11010
11000
00000

Answer: 1

Example 2:

11000
11000
00100
00011

Answer: 3

1.2思路

bfs,使用bfs可以将与1相邻的所有1全部标记为True,如果出现还没有被标记的1,则iland数量+1

1.3代码

class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        if not grid:
            return 0
        m = len(grid)
        n = len(grid[0])
        self.visited = [[False for i in range(n)] for j in range(m)]
        ans = 0
        for x in range(m):
            for y in range(n):
                if grid[x][y] == '1' and not self.visited[x][y]:
                    ans += 1
                    self.bfs(grid, x, y, m, n)
        return ans


    def bfs(self, grid, x, y, m, n):
        d = zip([1,0,-1,0],[0,1,0,-1])
        queue = [(x, y)]
        self.visited[x][y] = True
        while queue:
            x, y = queue.pop(0)
            for dx, dy in d:
                nx = x + dx
                ny = y + dy
                if nx >= 0 and nx < m and ny >= 0 and ny < n and grid[nx][ny] == '1' and not self.visited[nx][ny]:
                    self.visited[nx][ny] = True
                    queue.append((nx, ny))

2. 词语阶梯(LeetCode 127 Word Ladder)

2.1题目

Given two words (beginWord and endWord), and a dictionary’s word list, find the length of shortest transformation sequence from beginWord to endWord, such that:

Only one letter can be changed at a time.
Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
For example,

Given:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,”dot”,”dog”,”lot”,”log”,”cog”]
As one shortest transformation is “hit” -> “hot” -> “dot” -> “dog” -> “cog”,
return its length 5.

Note:
Return 0 if there is no such transformation sequence.
All words have the same length.
All words contain only lowercase alphabetic characters.
You may assume no duplicates in the word list.
You may assume beginWord and endWord are non-empty and are not the same.

2.2思路

遍历每个单词,逐一将每个单词中的每个单词的各个位置上的字母用’_’代替,并作为键,完整的单词作为值,逐一添加。这样的话值列表中的单词就是键中的邻接单词。使用bfs从起始单词开始,遍历其邻接单词,如果出现结束单词,就结束,否则将单词添加到队列中。

2.3代码

class Solution(object):
    def ladderLength(self, beginWord, endWord, wordList):
        """
        :type beginWord: str
        :type endWord: str
        :type wordList: List[str]
        :rtype: int
        """
        def word_to_dict(wordlist):
            d = {}
            for word in wordlist:
                for i in range(len(word)):
                    s = word[:i] +'_'+ word[i+1:]
                    d[s] = d.get(s, []) + [word]
            return d
        def bfs(beginword, endword, d):
            queue = [(beginword, 1)]
            visit = set()
            while queue:
                word, step = queue.pop(0)                
                if word not in visit:
                    visit.add(word)
                    if word == endword:
                        return step
                    for i in range(len(word)):
                        s = word[:i] +'_'+ word[i+1:]
                        nei_words = d.get(s, [])
                        for nei in nei_words:
                            if nei not in visit:
                                queue.append((nei, step + 1))
            return 0 
        d = word_to_dict(wordList)
        return bfs(beginWord, endWord, d)

3. 词语阶梯2 (LeetCode 126Word Ladder II)

3.1题目

Given two words (beginWord and endWord), and a dictionary’s word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:

Only one letter can be changed at a time
Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
For example,

Given:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,”dot”,”dog”,”lot”,”log”,”cog”]
Return

  [
    ["hit","hot","dot","dog","cog"],
    ["hit","hot","lot","log","cog"]
  ]

Note:
Return an empty list if there is no such transformation sequence.
All words have the same length.
All words contain only lowercase alphabetic characters.
You may assume no duplicates in the word list.
You may assume beginWord and endWord are non-empty and are not the same.

3.2思路

将起始单词设为起始层单词集合,遍历每一层的每个单词,用’abcdefghijklmnopqrstuvwxyz’中的一个字母代替原始单词中的各个位置的字母,生成新的单词,判断新的单词是否在给定的单词列表中,且该单词在上一层未使用过,则将该单词加入下一层的列表单词结合中,使用字典进行存储:形式为{子单词:父单词}。循环直到endword在父集合中或者该层单词列表为空。最后按照字典中的顺序从最后一个单词开始拼接,得到答案。

3.3代码

class Solution(object):
    def findLadders(self, beginWord, endWord, wordList):
        """
        :type beginWord: str
        :type endWord: str
        :type wordList: List[str]
        :rtype: List[List[str]]
        """
        wordSet = set([])
        for word in wordList:
            wordSet.add(word)

        level = set([beginWord])

        parents = collections.defaultdict(set)

        while level and endWord not in parents:
            next_level = collections.defaultdict(set)
            for word in level:
                for i in range(len(beginWord)):
                    p1 = word[:i]
                    p2 = word[i+1:]
                    for j in 'abcdefghijklmnopqrstuvwxyz':
                        # accelerate 
                        if word[i] != j:
                            childWord = p1 + j + p2
                            if childWord in wordSet and childWord not in parents:
                                next_level[childWord].add(word)
            level = next_level
            parents.update(next_level)

        res = [[endWord]]
        while res and res[0][0] !=beginWord:
            res = [[p]+r for r in res for p in parents[r[0]]]

        return res

4. 01矩阵 (LeetCode 542 01 Matrix)

4.1题目

Given a matrix consists of 0 and 1, find the distance of the nearest 0 for each cell.

The distance between two adjacent cells is 1.
Example 1:

Input:  
0 0 0
0 1 0
0 0 0
Output:
0 0 0
0 1 0
0 0 0

Example 2:

Input:
0 0 0
0 1 0
1 1 1
Output:
0 0 0
0 1 0
1 2 1

4.2思路

0的位置对应的答案一定为0,故只需讨论距离1最近的0的位置即可
使用队列
初始时,将matrix中所有1元素的位置加入队列。
循环,直到队列中的元素为空
step += 1
遍历队列中的元素,记当前元素为p,坐标为(x,y)
若p的上下左右元素包含0,则p的距离设为step,从队列中移除p(使用两个新的数组,一个表示移除的元素列表,一个表示剩下的元素列表),将上一步中移除的元素对应的matrix中的值设为0。

4.3代码

class Solution(object):
    def updateMatrix(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[List[int]]
        """
        h, w = len(matrix), len(matrix[0])
        ans = [[0 for i in range(w)] for j in range(h)]
        queue = [(x,y) for x in range(h) for y in range(w)  if matrix[x][y]]
        step = 0
        while queue:
            step += 1
            nqueue, mqueue = [], []
            for x, y in queue:
                zero = 0
                for dx, dy in zip((1,0,-1,0),(0,1,0, -1)):
                    nx, ny = x +dx, y + dy
                    if 0 <= nx < h and 0 <= ny < w and matrix[nx][ny] == 0:
                        zero += 1
                if zero:
                    ans[x][y] = step

                    mqueue.append((x,y))
                else:
                    nqueue.append((x,y))  
            for x, y in mqueue:
                matrix[x][y] = 0
            queue = nqueue
        return ans

5. 太平洋与大西洋的水流 (LeetCode 417 Pacific Atlantic Water Flow)

5.1题目

Given an m x n matrix of non-negative integers representing the height of each unit cell in a continent, the “Pacific ocean” touches the left and top edges of the matrix and the “Atlantic ocean” touches the right and bottom edges.

Water can only flow in four directions (up, down, left, or right) from a cell to another one with height equal or lower.

Find the list of grid coordinates where water can flow to both the Pacific and Atlantic ocean.

Note:
The order of returned grid coordinates does not matter.
Both m and n are less than 150.
Example:

Given the following 5x5 matrix:

  Pacific ~   ~   ~   ~   ~ 
       ~  1   2   2   3  (5) *
       ~  3   2   3  (4) (4) *
       ~  2   4  (5)  3   1  *
       ~ (6) (7)  1   4   5  *
       ~ (5)  1   1   2   4  *
          *   *   *   *   * Atlantic

Return:

[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (positions with parentheses in above matrix).

5.2思路

使用queue+bfs
初始化,左边、上边的点->{pacific},右边、上边的点->{Atlantic}
使用queue实现bfs
对pacific和atlantic中的每个点,先进先出,遍历其上下左右的点,如果其高度大于等于当前点,则将其加入队列和集合中。
最后求解{pacific}和{Atlantic}的交集即为所有可以流入太平洋和大西洋的点集。

5.3代码

class Solution(object):
    def pacificAtlantic(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[List[int]]
        """
        m = len(matrix)
        if m == 0:
            return []
        n = len(matrix[0])
        topedge = [(0, y) for y in range(n)]
        leftedge = [(x, 0) for x in range(1,m)]
        rightedge = [(x, n-1) for x in range(m)]
        bottomedge = [(m-1, y) for y in range(n)]
        pacific = set(topedge + leftedge)
        atlantic = set(rightedge + bottomedge)
        def bfs(vset):
            dz = zip((1,0,-1,0),(0,1,0,-1))
            queue = list(vset)
            while queue:
                hx, hy = queue.pop(0)
                for dx, dy in dz:
                    nx, ny = hx + dx, hy + dy
                    if 0 <= nx < m and 0 <= ny < n:
                        if matrix[nx][ny] >= matrix[hx][hy]:
                            if (nx,ny) not in vset:
                                queue.append((nx, ny))
                                vset.add((nx,ny))
        bfs(pacific)
        bfs(atlantic)
        ans = pacific & atlantic
        return map(list,ans)

6. 收集雨水2 (LeetCode 407 Trapping Rain WaterII)

6.1题目

Given an m x n matrix of positive integers representing the height of each unit cell in a 2D elevation map, compute the volume of water it is able to trap after raining.

Note:
Both m and n are less than 110. The height of each unit cell is greater than 0 and is less than 20,000.

Example:

Given the following 3x6 height map:
[
  [1,4,3,1,3,2],
  [3,2,1,3,2,4],
  [2,3,3,2,3,1]
]

Return 4.

6.2思路

bfs
记矩形的高度、宽度分别为m,n,令二维数组 peakMap[i][j]= p e a k M a p [ i ] [ j ] = ∞ ,表示矩形区域最多可以达到的水面高度,将矩形的四条边中的各点坐标加入队列q,并将各点对应的高度赋值给peakMap相同坐标;每次从q中弹出队头元素x,y,遍历其上下左右四个方向的点(nx,ny),尝试用max(peakMap[x][y], heightMap[nx][ny]) 更新 peakMap[nx][ny] 的当前值(取两者中的较小值)

6.3代码

class Solution(object):
    def trapRainWater(self, heightMap):
        """
        :type heightMap: List[List[int]]
        :rtype: int
        """

        if len(heightMap) < 3 or len(heightMap[0]) < 3: return 0
        m, n = len(heightMap), len(heightMap[0])
        peakMap = [[0x7fffffff for i in range(n)] for i in range(m)]
        q = []
        for i in range(m):
            for j in range(n):
                if i in (0, m-1) or j in (0, n-1):
                    peakMap[i][j] = heightMap[i][j]
                    q.append((i, j))
        while q:
            x, y = q.pop(0)
            for dx, dy in zip([-1,0,1,0],[0,-1,0,1]):
                nx, ny = x+dx, y+dy
                if nx >= 0 and nx < m and ny >= 0 and ny < n:
                    limit = max(peakMap[x][y], heightMap[nx][ny])
                    if peakMap[nx][ny] > limit:
                        peakMap[nx][ny] = limit
                        q.append((nx, ny))
        return sum(peakMap[x][y] - heightMap[x][y] for x in range(m) for y in range(n))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值