leetcode刷题笔记-DFS and BFS

559. Maximum Depth of N-ary Tree

easy

BFS

Given a n-ary tree, find its maximum depth.

The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

For example, given a 3-ary tree:

 

《leetcode刷题笔记-DFS and BFS》

 

We should return its max depth, which is 3.

Note:

  1. The depth of the tree is at most 1000.
  2. The total number of nodes is at most 5000.

思路:The solution uses ‘X’ to indicate the end of all nodes on a level in the queue. The ‘X’ gets added only after all the nodes from the same level are enqueued.

"""
# Definition for a Node.
class Node(object):
    def __init__(self, val, children):
        self.val = val
        self.children = children
"""
class Solution(object):
    def maxDepth(self, root):
        """
        :type root: Node
        :rtype: int
        """
        if not root: return 0
        if not root.children: return 1
        
        depth = 0
        q = [root, 'X']
        
        while len(q):
            node = q.pop(0)
            
            if node == 'X':
                depth += 1
                if len(q):
                    q.append('X')
                continue
            
            if node.children:
                for n in node.children:
                    q.append(n)
        
        return depth
            

690. Employee Importance

easy

You are given a data structure of employee information, which includes the employee’s unique id, his importance value and his directsubordinates’ id.

For example, employee 1 is the leader of employee 2, and employee 2 is the leader of employee 3. They have importance value 15, 10 and 5, respectively. Then employee 1 has a data structure like [1, 15, [2]], and employee 2 has [2, 10, [3]], and employee 3 has [3, 5, []]. Note that although employee 3 is also a subordinate of employee 1, the relationship is not direct.

Now given the employee information of a company, and an employee id, you need to return the total importance value of this employee and all his subordinates.

Example 1:

Input: [[1, 5, [2, 3]], [2, 3, []], [3, 3, []]], 1
Output: 11
Explanation:
Employee 1 has importance value 5, and he has two direct subordinates: employee 2 and employee 3. They both have importance value 3. So the total importance value of employee 1 is 5 + 3 + 3 = 11.
"""
# Employee info
class Employee(object):
    def __init__(self, id, importance, subordinates):
        # It's the unique id of each node.
        # unique id of this employee
        self.id = id
        # the importance value of this employee
        self.importance = importance
        # the id of direct subordinates
        self.subordinates = subordinates
"""
class Solution(object):
    def getImportance(self, employees, id):
        """
        :type employees: Employee
        :type id: int
        :rtype: int
        """
        d = {e.id: e for e in employees}
        res = 0
        q = [d[id]]
        while q:
            e = q.pop()
            res += e.importance
            for s in e.subordinates:
                q.append(d[s])
        return res

733. Flood Fill

easy DFS

An image is represented by a 2-D array of integers, each integer representing the pixel value of the image (from 0 to 65535).

Given a coordinate (sr, sc) representing the starting pixel (row and column) of the flood fill, and a pixel value newColor, “flood fill” the image.

To perform a “flood fill”, consider the starting pixel, plus any pixels connected 4-directionally to the starting pixel of the same color as the starting pixel, plus any pixels connected 4-directionally to those pixels (also with the same color as the starting pixel), and so on. Replace the color of all of the aforementioned pixels with the newColor.

At the end, return the modified image.

Example 1:

Input: 
image = [[1,1,1],[1,1,0],[1,0,1]]
sr = 1, sc = 1, newColor = 2
Output: [[2,2,2],[2,2,0],[2,0,1]]
Explanation: 
From the center of the image (with position (sr, sc) = (1, 1)), all pixels connected 
by a path of the same color as the starting pixel are colored with the new color.
Note the bottom corner is not colored 2, because it is not 4-directionally connected
to the starting pixel.
class Solution(object):
    def floodFill(self, image, sr, sc, newColor):
        """
        :type image: List[List[int]]
        :type sr: int
        :type sc: int
        :type newColor: int
        :rtype: List[List[int]]
        """
        visited = [[0]*len(image[0]) for i in image]
        return self.helper(image, visited, sr, sc, newColor, image[sr][sc])
        
    
    def helper(self, image, visited, sr, sc, newColor, oldColor):
        if not ( 0 <= sr < len(image) and 0 <= sc < len(image[0])) or visited[sr][sc] or image[sr][sc] != oldColor:
            return image
        
        image[sr][sc] = newColor
        visited[sr][sc] = 1
        offset = ((0, 1), (0, -1), (1, 0), (-1, 0))
        
        for off in offset:
            image = self.helper(image, visited, sr+off[0], sc+off[1], newColor, oldColor)
        
        return image

108. Convert Sorted Array to Binary Search Tree

easy  不知道这道题有什么意义

Given an array where elements are sorted in ascending order, convert it to a height balanced BST.

For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.

Example:

Given the sorted array: [-10,-3,0,5,9],

One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST:

      0
     / \
   -3   9
   /   /
 -10  5

思路:

For a sorted array, the left half will be in the left subtree, middle value as the root, right half in the right subtree. This holds through for every node:

[1, 2, 3, 4, 5, 6, 7] -> left: [1, 2, 3], root: 4, right: [5, 6, 7]
[1, 2, 3] -> left: [1], root: 2, right: [3]
[5, 6, 7] -> left: [5], root: 6, right: [7]

Many of the approaches here suggest slicing an array recursively and passing them. However, slicing the array is expensive. It is better to pass the left and right bounds into recursive calls instead.

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def sortedArrayToBST(self, nums):
        """
        :type nums: List[int]
        :rtype: TreeNode
        """
        def helper(left, right):
            if left > right:
                return None
            mid = (right + left) // 2
            node = TreeNode(nums[mid])
            node.left = helper(left, mid-1)
            node.right = helper(mid+1, right)
            return node
        
        return helper(0, len(nums)-1)

257. Binary Tree Paths

easy DFS stack

Given a binary tree, return all root-to-leaf paths.

Note: A leaf is a node with no children.

Example:

Input:

   1
 /   \
2     3
 \
  5

Output: ["1->2->5", "1->3"]

Explanation: All root-to-leaf paths are: 1->2->5, 1->3
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def binaryTreePaths(self, root):
        """
        :type root: TreeNode
        :rtype: List[str]
        """
        if not root:
            return []
        
        res, stack = [], [(root, "")] 
        
        while stack:
            node, string = stack.pop(0)
            if node.right:
                stack.append((node.right, string+str(node.val)+'->'))
            if node.left:
                stack.append((node.left, string+str(node.val)+'->'))
            if not node.left and not node.right:
                res.append(string + str(node.val)) 
            
        return res

111. Minimum Depth of Binary Tree

Given a binary tree, find its minimum depth.

The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.

Note: A leaf is a node with no children.

Example:

Given binary tree [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

return its minimum depth = 2.

DFS:
 

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def minDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        
        if None in (root.left, root.right):
            return max(self.minDepth(root.left), self.minDepth(root.right)) + 1
        else:
            return min(self.minDepth(root.left), self.minDepth(root.right)) + 1

513. Find Bottom Left Tree Value

Given a binary tree, find the leftmost value in the last row of the tree.

Example 1:

Input:

    2
   / \
  1   3

Output:
1

Example 2: 

Input:

        1
       / \
      2   3
     /   / \
    4   5   6
       /
      7

Output:
7
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def findBottomLeftValue(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        # BFS
        queue = [root]
        for node in queue:
            queue += filter(None, [node.right, node.left])
        return node.val

515. Find Largest Value in Each Tree Row

You need to find the largest value in each row of a binary tree.

Example:

Input: 

          1
         / \
        3   2
       / \   \  
      5   3   9 

Output: [1, 3, 9]

结合了前面题目的方法。

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def largestValues(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        res = []
        if not root:
            return res
        q = [root, "X"]
        maxValue = float('-inf')
        while q:
            node = q.pop(0)
            
            if node == 'X':
                res.append(maxValue)
                maxValue = float('-inf')
                if len(q):
                    q.append('X')
            else:
                q += filter(None, [node.left, node.right])
                maxValue = max(maxValue, node.val)
        
        return res

别人的解法,妈呀唉:

def findValueMostElement(self, root):
    maxes = []
    row = [root]
    while any(row):
        maxes.append(max(node.val for node in row))
        row = [kid for node in row for kid in (node.left, node.right) if kid]
    return maxes

547. Friend Circles

There are N students in a class. Some of them are friends, while some are not. Their friendship is transitive in nature. For example, if A is a direct friend of B, and B is a direct friend of C, then A is an indirect friend of C. And we defined a friend circle is a group of students who are direct or indirect friends.

Given a N*N matrix M representing the friend relationship between students in the class. If M[i][j] = 1, then the ith and jth students are direct friends with each other, otherwise not. And you have to output the total number of friend circles among all the students.

Example 1:

Input: 
[[1,1,0],
 [1,1,0],
 [0,0,1]]
Output: 2
Explanation:The 0th and 1st students are direct friends, so they are in a friend circle. 
The 2nd student himself is in a friend circle. So return 2.

 

Example 2:

Input: 
[[1,1,0],
 [1,1,1],
 [0,1,1]]
Output: 1
Explanation:The 0th and 1st students are direct friends, the 1st and 2nd students are direct friends, 
so the 0th and 2nd students are indirect friends. All of them are in the same friend circle, so return 1.

人都是0到N

class Solution(object):
    def findCircleNum(self, M):
        """
        :type M: List[List[int]]
        :rtype: int
        """
        visited = set()
        circle = 0
        def dfs(people):
            visited.add(people)
            for friend in xrange(len(M)):
                if M[people][friend] and friend not in visited:
                    dfs(friend)
                    
        for people in xrange(len(M)):
            if people not in visited:
                circle += 1
                dfs(people)
                
        return circle

638. Shopping Offers 

In LeetCode Store, there are some kinds of items to sell. Each item has a price.

However, there are some special offers, and a special offer consists of one or more different kinds of items with a sale price.

You are given the each item’s price, a set of special offers, and the number we need to buy for each item. The job is to output the lowest price you have to pay for exactly certain items as given, where you could make optimal use of the special offers.

Each special offer is represented in the form of an array, the last number represents the price you need to pay for this special offer, other numbers represents how many specific items you could get if you buy this offer.

You could use any of special offers as many times as you want.

Example 1:

Input: [2,5], [[3,0,5],[1,2,10]], [3,2]
Output: 14
Explanation: 
There are two kinds of items, A and B. Their prices are $2 and $5 respectively. 
In special offer 1, you can pay $5 for 3A and 0B
In special offer 2, you can pay $10 for 1A and 2B. 
You need to buy 3A and 2B, so you may pay $10 for 1A and 2B (special offer #2), and $4 for 2A.

Example 2:

Input: [2,3,4], [[1,1,0,4],[2,2,1,9]], [1,2,1]
Output: 11
Explanation: 
The price of A is $2, and $3 for B, $4 for C. 
You may pay $4 for 1A and 1B, and $9 for 2A ,2B and 1C. 
You need to buy 1A ,2B and 1C, so you may pay $4 for 1A and 1B (special offer #1), and $3 for 1B, $4 for 1C. 
You cannot add more items, though only $9 for 2A ,2B and 1C.

Note:

  1. There are at most 6 kinds of items, 100 special offers.
  2. For each item, you need to buy at most 6 of them.
  3. You are not allowed to buy more items than you want, even if that would lower the overall price.

这个写法太好了,很简洁直接。

class Solution(object):
    def shoppingOffers(self, price, special, needs):
        """
        :type price: List[int]
        :type special: List[List[int]]
        :type needs: List[int]
        :rtype: int
        """
        d = {}
        
        def dfs(curNeeds):
            val = sum(curNeeds[i]*price[i] for i in xrange(len(needs)))  # cost without special
            for spec in special:
                tmpNeeds = [curNeeds[j] - spec[j] for j in xrange(len(needs))]
                if min(tmpNeeds) >= 0:
                    val = min(val, d.get(tuple(tmpNeeds), dfs(tmpNeeds)) + spec[-1])
            d[tuple(tmpNeeds)] = val
            return val
        
        return dfs(needs)

337. House Robber III 

The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the “root.” Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that “all houses in this place forms a binary tree”. It will automatically contact the police if two directly-linked houses were broken into on the same night.

Determine the maximum amount of money the thief can rob tonight without alerting the police.

Example 1:

Input: [3,2,3,null,3,null,1]

     3
    / \
   2   3
    \   \ 
     3   1

Output: 7 
Explanation: Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.

Example 2:

Input: [3,4,5,1,3,null,1]

     3
    / \
   4   5
  / \   \ 
 1   3   1

Output: 9
Explanation: Maximum amount of money the thief can rob = 4 + 5 = 9.

 

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def rob(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        
        def superRob(node):
            # returns tuple of size two (now, later)
            # now: max money earned if input node is robbed
            # later: max money earned if input node is not robbed
            if not node: return (0, 0)
            
            left, right = superRob(node.left), superRob(node.right)
            
            # rob now
            now = node.val + left[1] + right[1]
            # rob later
            later = max(left) + max(right)
            
            return now, later
        
        return max(superRob(root))

199. Binary Tree Right Side View 

Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.

Example:

Input: [1,2,3,null,5,null,4]
Output: [1, 3, 4]
Explanation:

   1            <---
 /   \
2     3         <---
 \     \
  5     4       <---

和之前的题目方法一样,每层的Node放到queue中

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def rightSideView(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        if not root:
            return []
        q = [root]
        res = []
        while q:
            res.append(q[-1].val)
            q = [kid for node in q for kid in (node.left, node.right) if kid]
        return res

129. Sum Root to Leaf Numbers

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.

An example is the root-to-leaf path 1->2->3 which represents the number 123.

Find the total sum of all root-to-leaf numbers.

Note: A leaf is a node with no children.

Example:

Input: [1,2,3]
    1
   / \
  2   3
Output: 25
Explanation:
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.
Therefore, sum = 12 + 13 = 25.

Example 2:

Input: [4,9,0,5,1]
    4
   / \
  9   0
 / \
5   1
Output: 1026
Explanation:
The root-to-leaf path 4->9->5 represents the number 495.
The root-to-leaf path 4->9->1 represents the number 491.
The root-to-leaf path 4->0 represents the number 40.
Therefore, sum = 495 + 491 + 40 = 1026.

标准的DFS:

class Solution(object):
    def sumNumbers(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        # dfs
        stack = [[root, root.val]]
        res = 0
        while stack:
            
            node, value = stack.pop()
            if node.left:
                stack.append([node.left, value*10+node.left.val])
            if node.right:
                stack.append([node.right, value*10+node.right.val])
            if not node.left and not node.right:
                res += value
                
        return res

BFS

class Solution(object):
    def sumNumbers(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        # dfs
        stack = [[root, root.val]]
        res = 0
        while stack:
            
            node, value = stack.pop(0)
            if node.left:
                stack.append([node.left, value*10+node.left.val])
            if node.right:
                stack.append([node.right, value*10+node.right.val])
            if not node.left and not node.right:
                res += value
                
        return res

 

200. 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:

Input:
11110
11010
11000
00000

Output: 1

Example 2:

Input:
11000
11000
00100
00011

Output: 3

第一次解法超时:

class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        
        def dfs(row, col):
            if  row < 0 or row >= len(grid) or col < 0 or col >= len(grid[0]):
                return
             
            if visited[row][col]:
                return
            else:
                visited[row][col] = 1
            
            if grid[row][col] == 0: return
            for i, j in ([0, 1], [0, -1], [1, 0], [-1, 0]):
                dfs(row+i, col+j)

        
        visited = [[0]*len(grid[0]) for i in grid]
        count = 0
        for row in xrange(len(grid)):
            for col in xrange(len(grid[0])):
                if grid[row][col] and visited[row][col] == 0:
                    count += 1
                    dfs(row, col)
        
        return count

参考别人的解法后不用visited来判断是否访问过,直接在原grid上把访问过的改成‘#’,其他思路一样

class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        if not grid:
            return 0
        
        def dfs(row, col):
            if  row < 0 or row >= len(grid) or col < 0 or col >= len(grid[0]) or grid[row][col] != '1':
                return
            grid[row][col] = '#'
            for i, j in ([0, 1], [0, -1], [1, 0], [-1, 0]):
                dfs(row+i, col+j)

        count = 0
        for row in xrange(len(grid)):
            for col in xrange(len(grid[0])):
                if grid[row][col] == '1':
                    count += 1
                    dfs(row, col)
        return count

116. Populating Next Right Pointers in Each Node

too esay, 一遍过,beats 100%

Given a binary tree

struct TreeLinkNode {
  TreeLinkNode *left;
  TreeLinkNode *right;
  TreeLinkNode *next;
}

Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.

Initially, all next pointers are set to NULL.

Note:

  • You may only use constant extra space.
  • Recursive approach is fine, implicit stack space does not count as extra space for this problem.
  • You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children).

Example:

Given the following perfect binary tree,

     1
   /  \
  2    3
 / \  / \
4  5  6  7

After calling your function, the tree should look like:

     1 -> NULL
   /  \
  2 -> 3 -> NULL
 / \  / \
4->5->6->7 -> NULL
class Solution:
    # @param root, a tree link node
    # @return nothing
    def connect(self, root):
        if not root:
            return root
        
        q = [root]
        right = None
        while q:
            for node in q:
                node.next = right
                right = node
            right = None    
            q = [kid for node in q for kid in (node.right, node.left) if kid]
            

473. Matchsticks to Square

Remember the story of Little Match Girl? By now, you know exactly what matchsticks the little match girl has, please find out a way you can make one square by using up all those matchsticks. You should not break any stick, but you can link them up, and each matchstick must be used exactly one time.

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.

Example 1:

Input: [1,1,2,2,2]
Output: true

Explanation: You can form a square with length 2, one side of the square came two sticks with length 1.

Example 2:

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

Explanation: You cannot find a way to form a square with all the matchsticks.
class Solution(object):
    def makesquare(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        s = sum(nums)
        if s % 4 or len(nums) < 4 or max(nums) > s / 4:
            return False

        def dfs(nums, index, target):
            if index == len(nums): return True
            for i in xrange(4):
                if target[i] >= nums[index]:
                    target[i] -= nums[index]
                    if dfs(nums, index + 1, target): return True
                    target[i] += nums[index]

            return False

        s /= 4
        n = len(nums)
        nums.sort(reverse=True)
        target = [s] * 4
        return dfs(nums, 0, target)
点赞