Leetcode 314: Binary Tree Vertical Order Traversal

314. Binary Tree Vertical Order Traversal 

  • Total Accepted: 13025
  • Total Submissions: 38434
  • Difficulty: Medium
  • Contributors: Admin

Given a binary tree, return the vertical order traversal of its nodes’ values. (ie, from top to bottom, column by column).

If two nodes are in the same row and column, the order should be from left to right.

Examples:

  1. Given binary tree [3,9,20,null,null,15,7],
       3
      /\
     /  \
     9  20
        /\
       /  \
      15   7
    

    return its vertical order traversal as:

    [
      [9],
      [3,15],
      [20],
      [7]
    ]
    
  2. Given binary tree [3,9,8,4,0,1,7],
         3
        /\
       /  \
       9   8
      /\  /\
     /  \/  \
     4  01   7
    

    return its vertical order traversal as:

    [
      [4],
      [9],
      [3,0,1],
      [8],
      [7]
    ]
    
  3. Given binary tree [3,9,8,4,0,1,7,null,null,null,2,5] (0’s right child is 2 and 1’s left child is 5),
         3
        /\
       /  \
       9   8
      /\  /\
     /  \/  \
     4  01   7
        /\
       /  \
       5   2
    

    return its vertical order traversal as:

    [
      [4],
      [9,5],
      [3,0,1],
      [8,2],
      [7]
    ]
    
Show Company Tags
Show Tags
Show Similar Problems
 

 

Code

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

from collections import defaultdict, deque

class Solution(object):
    def verticalOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if root is None:
            return []

        d = defaultdict(list)
        l = deque([(root,0)])
     
        while l:
            n, v = l.popleft()
            d[v].append(n.val)
            if n.left: 
                l.append((n.left, v-1))
            if n.right: 
                l.append((n.right, v+1))

        res = []
        for k in sorted(d.keys()):
            res.append(d[k])
        
        return res

 

Idea

Use BFS to traverse nodes. Since result must take O(N) space anyway, I don’t think there is much room to improve. 

Leetcode 155: Min Stack

155. Min Stack

  • Total Accepted: 96784
  • Total Submissions: 383098
  • Difficulty: Easy
  • Contributors: Admin

Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.

  • push(x) — Push element x onto stack.
  • pop() — Removes the element on top of the stack.
  • top() — Get the top element.
  • getMin() — Retrieve the minimum element in the stack.

Example:

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> Returns -3.
minStack.pop();
minStack.top();      --> Returns 0.
minStack.getMin();   --> Returns -2.

 

Code

import sys

class MinStack(object):

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.min = sys.maxint
        self.stk = []

    def push(self, x):
        """
        :type x: int
        :rtype: void
        """
        if x <= self.min:
            self.stk.append(self.min)
            self.min = x
        self.stk.append(x)
        

    def pop(self):
        """
        :rtype: void
        """
        if self.stk:
            if self.stk[-1] == self.min:
                self.min = self.stk[-2]
                self.stk.pop()
            self.stk.pop()

    def top(self):
        """
        :rtype: int
        """
        if self.stk:
            return self.stk[-1]

    def getMin(self):
        """
        :rtype: int
        """
        if self.stk:
            return self.min
        


# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()

 

Idea

Whenever self.min changes, push the old self.min into stack. When popping an element equal to self.min, then the previous element in the stack is self.min before the element was added.

You can also add self.min along with the new element every time you execute push: https://discuss.leetcode.com/topic/11985/my-python-solution

Finding missing k numbers in 0…N-1

This is the interview question from http://stackoverflow.com/questions/3492302/easy-interview-question-got-harder-given-numbers-1-100-find-the-missing-numbe?rq=1:

You are given a bag of numbers which are 0 ~ N-1 integers except k numbers. Return the k missing numbers. The solution should operate in O(N) time complexity and O(k) space complexity.

Although the highest voted post uses some theorem to solve the question, I would like to expand another solution which seems more intuitive and practical.

 

Code

class Solution(object):
    def find_k_missing(self, a, n):
        k = n - len(a)
        if k == 0:
            return a
        elif k == n:
            return range(n)

        a.extend([a[0]] * k)

        for i in xrange(n):
            while a[i] != a[a[i]]:
                t = a[i]
                a[i] = a[a[i]]
                a[t] = t

        return [idx for idx, v in enumerate(a) if idx != v]


if __name__ == "__main__":
    s = Solution()
    print s.find_k_missing([3,1,0,4], 5)

 

 

Idea

Suppose we have a bag a which contains the N-k numbers.

  1. Extend the a with k additional numbers. The k additional numbers are set as the same value as any existing number, say, a[0]. After this step, a has N numbers.
  2. We want to reorder a such that a[j] == j for j in the original N-k numbers.  To do so, traverse every number a[i] in a: swap a[i] and a[a[i]] until a[a[i]] == a[i]. This makes sure at least a[a[i]] == a[i] after the swap, which means a[a[i]] will be associated with the correct number.
  3. Then, any position a[j] != j denotes the missing number.

 

 

Reference:

http://pastebin.com/9jZqnTzV

Leetcode 311: Sparse Matrix Multiplication

311. Sparse Matrix Multiplication

  • Total Accepted: 13356
  • Total Submissions: 26970
  • Difficulty: Medium
  • Contributors: Admin

Given two sparse matrices A and B, return the result of AB.

You may assume that A‘s column number is equal to B‘s row number.

 

Code

from collections import defaultdict

class Solution(object):
    def multiply(self, A, B):
        """
        :type A: List[List[int]]
        :type B: List[List[int]]
        :rtype: List[List[int]]
        """
        C = [[0] * len(B[0]) for i in xrange(len(A))]
        
        # cache for A
        dA = defaultdict(lambda: defaultdict(int))
        for i in xrange(len(A)):
            for j in xrange(len(A[0])):
                if A[i][j]:
                    dA[i][j] = A[i][j]

        # cache for B
        dB = defaultdict(lambda: defaultdict(int))
        for i in xrange(len(B)):
            for j in xrange(len(B[0])):
                if B[i][j]:
                    dB[i][j] = B[i][j]

        # only calculate necessary elements
        for i in dA:
            for j, Aij in dA[i].iteritems():
                for k, Bjk in dB[j].iteritems():
                    C[i][k] += Aij * Bjk

        return C

 

Idea

If you calculate $latex C_{ik} = \sum\limits_j A_{ij} \cdot B_{jk}$, the total time complexity is O(N^3) (assume A, B and C have size O(N^2).)

To speed it up, you need to cache non-zero of A and B. And calculate $latex A_{ij} \cdot B_{jk}$ when necessary. 

Leetcode 237: Delete Node in a Linked List

237. Delete Node in a Linked List

  • Total Accepted: 114749
  • Total Submissions: 255293
  • Difficulty: Easy
  • Contributors: Admin

Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.

Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4after calling your function.

 

Code

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def deleteNode(self, node):
        """
        :type node: ListNode
        :rtype: void Do not return anything, modify node in-place instead.
        """
        node.val = node.next.val
        tmp = node.next.next
        node.next.next = None
        node.next = tmp

 

Idea

Replace this node with this node’s next node.

 

Leetcode 117: Populating Next Right Pointers in Each Node II

117. Populating Next Right Pointers in Each Node II 

  • Total Accepted: 74952
  • Total Submissions: 225622
  • Difficulty: Hard
  • Contributors: Admin

Follow up for problem “Populating Next Right Pointers in Each Node“.

What if the given tree could be any binary tree? Would your previous solution still work?

Note:

  • You may only use constant extra space.

For example,
Given the following binary tree,

         1
       /  \
      2    3
     / \    \
    4   5    7

After calling your function, the tree should look like:

         1 -> NULL
       /  \
      2 -> 3 -> NULL
     / \    \
    4-> 5 -> 7 -> NULL

 

Code 

from collections import deque
# Definition for binary tree with next pointer.
# class TreeLinkNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
#         self.next = None

class Solution:
    # @param root, a tree link node
    # @return nothing
    def connect(self, root):
        if root is None:
            return

        d = deque([(root, 0)])
        
        while d:
            if len(d) >= 2:
                # level is the same
                if d[0][1] == d[1][1]:
                    d[0][0].next = d[1][0]
                
            old_node, old_lvl = d.popleft()
            if old_node.left: d.append((old_node.left, old_lvl + 1))
            if old_node.right: d.append((old_node.right, old_lvl + 1))

 

Idea

Using BFS. Also look at the similar problem: https//nb4799.neu.edu/wordpress/?p=2044. Time complexity and space complexity are both O(N).

 

Code

# Definition for binary tree with next pointer.
# class TreeLinkNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
#         self.next = None

class Solution:
    
    def find_child(self, node, start_from_left_or_right):
        """ find the first occurrence of a child from the level of node.

        Return:
        1. child node
        2. its parent node
        3. "left" if it is the left child of its parent, otherwise "right"

        If child node is not found, return (None, None, None)
        """
        
        if node and start_from_left_or_right == 'right':
            if node.right:
                return node.right, node, 'right'
            else:
                node = node.next

        while node:
            if node.left:
                return node.left, node, 'left'
            elif node.right:
                return node.right, node, 'right'
            else:
                node = node.next

        return None, None, None


    # @param root, a tree link node
    # @return nothing
    def connect(self, root):
        if root is None: 
            return
        
        # pre is the first node in the previous layer
        pre = root
        
        while pre:
            # search the first child in the current layer
            first_child, first_child_parent, first_child_as_left_or_right = self.find_child(pre, 'left')
            pre = first_child

            while first_child is not None:
                # search the next child in the current layer
                if first_child_as_left_or_right == "left":
                    second_child, second_child_parent, second_child_as_left_or_right = \
                        self.find_child(first_child_parent, 'right')
                else:
                    second_child, second_child_parent, second_child_as_left_or_right = \
                        self.find_child(first_child_parent.next, 'left')
                
                if second_child is not None:
                    first_child.next = second_child
                    
                first_child, first_child_parent, first_child_as_left_or_right = \
                    second_child, second_child_parent, second_child_as_left_or_right                 



            
                

 

 

Idea

Modified from the O(1) space solution from: https//nb4799.neu.edu/wordpress/?p=2044

 

 

Leetcode 371: Sum of Two Integers

371. Sum of Two Integers 

  • Total Accepted: 42501
  • Total Submissions: 82322
  • Difficulty: Easy
  • Contributors: Admin

Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -.

Example:
Given a = 1 and b = 2, return 3.

 

Code

class Solution(object):
    def getSum(self, a, b):
        """
        :type a: int
        :type b: int
        :rtype: int
        """
        if a == 0:
            return b
        elif b == 0:
            return a
        
        mask = 0xffffffff

        # in Python, every integer is associated with its two's complement and its sign.
        # However, doing bit operation "& mask" loses the track of sign. 
        # Therefore, after the while loop, a is the two's complement of the final result as a 32-bit unsigned integer. 
        while b != 0:
            a, b = (a ^ b) & mask, ((a & b) << 1) & mask

        # a is negative if the first bit is 1
        if (a >> 31) & 1:
            return ~(a ^ mask)
        else:
            return a

 

Idea

Adding two integers a and b (no matter positive or negative) can always be boiled down into 3 steps:

  1. convert a and b into two’s complements.
  2. add both two’s complements. The result is a new two’s complement
  3. convert the result back to integer

 

Two things to note:
1. In Python, every integer is associated with its two’s complement and its sign. However, doing bit operation “& mask” loses the track of sign. For example, `-1 & 0xffffffff` becomes a huge positive number 4294967295. Therefore, after the while loop, a is the two’s complement of the final result as a **32-bit unsigned integer**.
2. The magic is that if there is a negative integer `n`, and its unsigned 32-bit two’s complement is `m`, then `m = ~(n ^ 0xffffffff)` and `n = ~(m ^ 0xffffffff)`. So using this magic, you can do the conversion in step 3.

 

Reference: https://discuss.leetcode.com/topic/65027/most-straightforward-python-solution

Leetcode 292: Nim Game

292. Nim Game

 
  • Total Accepted: 105850
  • Total Submissions: 194593
  • Difficulty: Easy
  • Contributors: Admin

You are playing the following Nim Game with your friend: There is a heap of stones on the table, each time one of you take turns to remove 1 to 3 stones. The one who removes the last stone will be the winner. You will take the first turn to remove the stones.

Both of you are very clever and have optimal strategies for the game. Write a function to determine whether you can win the game given the number of stones in the heap.

For example, if there are 4 stones in the heap, then you will never win the game: no matter 1, 2, or 3 stones you remove, the last stone will always be removed by your friend.

Hint:

  1. If there are 5 stones in the heap, could you figure out a way to remove the stones such that you will always be the winner?

 

Code

from collections import deque

class Solution(object):
    def canWinNim(self, n):
        """
        :type n: int
        :rtype: bool
        """
        if n <= 3:
            return True

        # when n = 1,2,3, you can always win
        d = deque([True] * 3)
        
        for i in xrange(4, n+1):
            newd = not (d[0] and d[1] and d[2])
            d.popleft()
            d.append(newd)

        return d[-1]

 

Idea

d contains three elements: when there are i-3, i-2 and i-1 remaining stones, can one have an optimal strategy to win? If they are all trues, no matter how many stones you take, your opponent will win.

 

Of course, this can be equivalent to: 

class Solution(object):
    def canWinNim(self, n):
        """
        :type n: int
        :rtype: bool
        """
        return n % 4 != 0

 

 

Leetcode 137: Single Number II

137. Single Number II

  • Total Accepted: 100365
  • Total Submissions: 253451
  • Difficulty: Medium
  • Contributors: Admin

Given an array of integers, every element appears three times except for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

 
Code
class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        ans = 0

        for i in xrange(32):
            sum = 0
            for n in nums:
                # right shift in Python is unsigned
                # i.e., leftmost is filled with 0
                sum += (abs(n) >> i) & 1
            sum = sum % 3
            if sum != 0:
                ans = ans | (1 << i)
        
        negsign = 0
        for n in nums:
           if n < 0:
               negsign += 1
        negsign = negsign % 3
            
        if negsign != 0 :
            return -ans
        else:
            return ans

 

 
 
Idea
Although there is a convoluted algorithm using bit operation to solve this problem, I feel it is impossible to come up with that during an interview. 
 
suppose an integer is 32 bit. For each bit position, count how many numbers in nums are non-zero on that bit and store the count in sum.  When sum % 3 != 0, you know the exceptional number has 1 on that bit. (The prerequisite is that the exceptional number appears k times in nums where k % 3 != 0. This is the condition that the question does not specify right now but it did in the previous version.)
 
Integers in Python are not  implemented as fixed-size bits. The right shift in Python is unsigned (the leftmost position is filled with 0). Therefore, we need to count separately whether the exceptional number is negative or positive. (line 19-23)

Leetcode 72: Edit Distance

72. Edit Distance

  • Total Accepted: 71110
  • Total Submissions: 236049
  • Difficulty: Hard
  • Contributors: Admin

Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)

You have the following 3 operations permitted on a word:

a) Insert a character
b) Delete a character
c) Replace a character

 

Code

class Solution(object):
    def minDistance(self, word1, word2):
        """
        :type word1: str
        :type word2: str
        :rtype: int
        """
        d = [[0]*(len(word2)+1) for i in xrange(len(word1)+1)]
        
        for i in xrange(len(word1)+1):
            d[i][0] = i

        for j in xrange(len(word2)+1):
            d[0][j] = j

        for i in xrange(1, len(word1)+1):
            for j in xrange(1, len(word2)+1):
                if word1[i-1] == word2[j-1]:
                    d[i][j] = d[i-1][j-1]
                else:
                    d[i][j] = min(d[i-1][j]+1,   # delete word1[i]
                                  d[i][j-1]+1,   # delete word2[j]
                                  d[i-1][j-1]+1  # replace word1[i] by word2[j]
                                  )
        return d[-1][-1] 

 

 

Idea

We maintain a 2D array d, where d[i][j] means the edit distance between the substring word1[:i] and word2[:j]

 

Code

class Solution(object):
    def minDistance(self, word1, word2):
        """
        :type word1: str
        :type word2: str
        :rtype: int
        """
        d = [i for i in xrange(len(word1)+1)]
      
        for j in xrange(1, len(word2)+1):
            pre = d[0]
            d[0] = j
            for i in xrange(1, len(word1)+1):      
                if word1[i-1] == word2[j-1]:
                    d[i], pre = pre, d[i]
                else:
                    d[i], pre = min(d[i-1]+1,  # delete word1[i]
                                    d[i]+1,    # delete word2[j]
                                    pre+1      # replace word1[i] by word2[j]
                                   ), d[i]
        return d[-1] 

 

Idea

Convert the 2D DP matrix into 1D. pre is the value of d[i-1][j-1] when d is 2D.

 

Reference

https://discuss.leetcode.com/topic/17639/20ms-detailed-explained-c-solutions-o-n-space