数据结构与算法分类练习--DFS BFS

深度优先遍历:对每一个可能的分支路径深入到不能再深入为止,不全部保留结点,占用空间少;有回溯操作(即有入栈、出栈操作),运行速度慢。

广度优先遍历:又叫层次遍历,从上往下对每一层依次访问,在每一层中,从左往右(也可以从右往左)访问结点,访问完一层就进入下一层,保留全部结点,占用空间大; 常用优先队列,无回溯操作,运行速度快。

Number of Islands 小岛数量

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

这道题的本质是求矩阵中连续区域的个数,我们使用DFS来解。找到一个为“1”的位置后总和加1,并递归的将其四周为“1”的位置置“0”。然后寻找下一个为“1”的位置。

class Solution(object):    
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        if not grid:
            return 0
        m = len(grid[0])
        n = len(grid)
        def sink (x, y):
            if 0 <= x < n and 0 <= y < m and grid[x][y] == '1':
                grid[x][y] = '0'
                map(sink, [x-1, x+1, x, x], [y, y, y-1, y+1])
                return 1
            return 0
        return sum(sink(x, y) for x in xrange(n) for y in xrange(m))

Matchsticks to Square 火柴棍能否组成正方形

Your input will be several matchsticks the girl has, represented with their stick length. Your output will either be true or false, to represent whether you could make one square using all the matchsticks the little match girl has.You should not break any stick, but you can link them up, and each matchstick must be used exactly one time.

Example: Input: [3,3,3,3,4] Output: false

我们可以使用位运算来表示数组中每个位置的状态。用used_subsets记录总和为边长的子数组V,用valid_half_subsets来记录两个V加起来和为周长的一半的子数组W。遍历所有子数组,如果当前子数组的和正好为边长,然后判断是否能和其他已知的V位置不重叠,如果有则进行组合存入valid_half_subsets,剩余的数值如果也存在valid_half_subsets中则返回Ture。

class Solution(object):
    def makesquare(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        total_len = sum(nums)
        if total_len % 4:
            return False

        side_len = total_len / 4
        fullset = (1 << len(nums)) - 1

        used_subsets = []
        valid_half_subsets = [0] * (1 << len(nums))

        for subset in xrange(fullset+1):
            # 遍历所有子数组
            subset_total_len = 0
            for i in xrange(len(nums)): 
                if subset & (1 << i):
                    subset_total_len += nums[i]

            if subset_total_len == side_len:
                for used_subset in used_subsets:
                    if (used_subset & subset) == 0:
                        valid_half_subset = used_subset | subset
                        valid_half_subsets[valid_half_subset] = True
                        if valid_half_subsets[fullset ^ valid_half_subset]:
                            return True
                used_subsets.append(subset)
        return False

Increasing Subsequences 递增子序列

Given an integer array, your task is to find all the different possible increasing subsequences of the given array, and the length of an increasing subsequence should be at least 2 .The given array may contain duplicates, and two equal integers should also be considered as a special case of increasing sequence.

和普通的生成子序列有两点不同:第一是需要去重,可以通过set()来辅助实现,最后再变回列表;第二是递增,可以在生成子序列的时候进行对比,看当前的数值是否不小于要扩充的子序列的最后一个数值。

Example: Input: [4, 6, 7, 7] Output: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]

class Solution(object):
    def findSubsequences(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        tmp = set()
        for n in nums:
            for y in list(tmp):
                if n >= y[-1]:
                    tmp.add(y + (n,))
            tmp.add((n,))
        return list(e for e in tmp if len(e) > 1)

附tmp的部分运行状态:

Word Ladder 词语阶梯

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:

  1. Only one letter can be changed at a time.
  2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
  3. All words have the same length.

Example:

Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"] Output: 5 "hit" -> "hot" -> "dot" -> "dog" -> "cog"

从beginword开始,对每个字符进行替换,如果替换后的单词在wordlist里则将其加入next集合中,供下一轮遍历;如果替换后的单词是backward则之接返回length。

class Solution(object):
    def ladderLength(self, beginWord, endWord, wordList):
        """
        :type beginWord: str
        :type endWord: str
        :type wordList: List[str]
        :rtype: int
        """
        wordList = set(wordList)
        forward, backward, length = {beginWord}, {endWord}, 2
        dic = set(string.ascii_lowercase)
        if endWord not in wordList:return 0
        while forward and backward:
            next = set()
            for word in forward:
                for i in range(len(word)):
                    first, second = word[:i], word[i + 1:]
                    for item in dic:
                        candidate = first + item + second
                        if candidate in backward:
                            return length
                        if candidate in wordList:
                            wordList.discard(candidate)
                            next.add(candidate)
            forward = next
            length += 1
        return 0

Pacific Atlantic Water Flow 太平洋大西洋水流

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.

Given the following 5x5 matrix:

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

从四条边开始逆流遍历,最后取左上两边能到达的地方和右下两边能达到的地方的交集即可。

class Solution(object):
    def pacificAtlantic(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[List[int]]
        """
        if not matrix: return []
        m,n = len(matrix), len(matrix[0])
        
        pacific = set([(i,0) for i in range(m)] + [(0,j) for j in range(n)])
        atlantic = set([(i,n-1) for i in range(m)] + [(m-1,j) for j in range(n)])
        
        def bfs(s):
            q=list(s)
            while q:
                i,j = q.pop(0)
                for di,dj in (0,1),(1,0),(0,-1),(-1,0):
                    ii,jj = i+di,j+dj
                    if 0<=ii<m and 0<=jj<n and matrix[ii][jj]>=matrix[i][j] and (ii,jj) not in s:
                        s.add((ii,jj))
                        q.append((ii,jj))
            return s
        
        return list(bfs(pacific) & bfs(atlantic))

Trapping Rain Water II 收集雨水

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.

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.

利用优先队列,将四周的高度/坐标存入,从最低点开始遍历四周,模拟海平面上升。如果发现未访问过的点,进行标记不再访问,如果高度低于当前高度则将存水量加入curr_res并以此点为中心继续向四周遍历。

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, pq = len(heightMap), len(heightMap[0]), []
        for i, j in zip([0]*n + range(1, m-1)*2 + [m-1]*n, range(n)+[0]*(m-2)+[n-1]*(m-2)+range(n)):
            heapq.heappush(pq, (heightMap[i][j], i, j))
            heightMap[i][j] = -1
        #do dfs
        res = 0
        def dfs(i, j, curr_height, curr_res):
            for next_i, next_j in ((i+1, j), (i-1, j), (i, j+1), (i, j-1)):
                if 0<=next_i<len(heightMap) and 0<=next_j<len(heightMap[0]) and heightMap[next_i][next_j] >= 0:
                    new_height = heightMap[next_i][next_j]
                    heightMap[next_i][next_j] = -1
                    if new_height < curr_height:
                        #we can secure how much water?
                        curr_res += curr_height-new_height
                        #continue to expand
                        curr_res = dfs(next_i, next_j, curr_height, curr_res)  
                    else:
                        heapq.heappush(pq, (new_height, next_i, next_j))
                
            return curr_res
        
        #for all the boundary points...
        while pq:
            curr_height, curr_i, curr_j = heapq.heappop(pq)
            res = dfs(curr_i, curr_j, curr_height, res)
        return res

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值