Leetcode 89: Gray Code

https://leetcode.com/problems/gray-code/

The gray code is a binary numeral system where two successive values differ in only one bit.

Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0.

For example, given n = 2, return [0,1,3,2]. Its gray code sequence is:

00 - 0
01 - 1
11 - 3
10 - 2

Note:
For a given n, a gray code sequence is not uniquely defined.

For example, [0,2,3,1] is also a valid gray code sequence according to the above definition.

For now, the judge is able to judge based on one instance of gray code sequence. Sorry about that.

 

Code

class Solution(object):
    def grayCode(self, n):
        """
        :type n: int
        :rtype: List[int]
        """
        if n<0:
            return []
        
        res = [0]
        for i in xrange(n):
            for j in xrange(len(res)-1, -1, -1):
                res.append(res[j] + (1 << i))
        return res

 

Idea

Say we have already had the gray codes for n. Then, the gray codes for n+1 are constituted from:

  1. ‘0’ followed by the gray codes for n
  2. ‘1’ followed by the gray codes for n in the reversed order

 

Leetcode 95: Unique Binary Search Trees II

https://leetcode.com/problems/unique-binary-search-trees-ii/

Given n, generate all structurally unique BST’s (binary search trees) that store values 1…n.

For example,
Given n = 3, your program should return all 5 unique BST’s shown below.

   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3

 

Code

# 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 copy(self, root, bias):
        if not root:
            return root
        
        new_root = TreeNode(root.val + bias)
        new_root.left = self.copy(root.left, bias)
        new_root.right = self.copy(root.right, bias)
        return new_root
        
    def generateTrees(self, n):
        """
        :type n: int
        :rtype: List[TreeNode]
        """
        if n == 0:
            return []
            
        ans = [[] for _ in xrange(n+1)]
        ans[0] = [None]
        
        for i in xrange(1, n+1):
            for j in xrange(1, i+1):    # j is the root value
                for lt in ans[j-1]:
                    for rt in ans[i-j]:
                        root = TreeNode(j)
                        root.left = self.copy(lt, 0)
                        root.right = self.copy(rt, j)
                        ans[i] += [root]
        return ans[-1]

 

Idea

To extend the idea of Leetcode 96, when you are given `n`, you can put `1~n` as roots. When you put `i` (`1<=i<=n`) as the root, the left tree is depending on the result of `i-1` and the right tree is depending on the result of `n-i`. For this problem, the right tree is not solely copy of the trees of `n-i`. Every node in the trees of `n-i` should be added a bias of `i`. Therefore, we create a recursive function `copy(self, root, bias)` to copy trees with biases. 

Leetcode 96: Unique Binary Search Trees

https://leetcode.com/problems/unique-binary-search-trees/

Given n, how many structurally unique BST’s (binary search trees) that store values 1…n?

For example,
Given n = 3, there are a total of 5 unique BST’s.

   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3

 

Code

class Solution(object):
    def numTrees(self, n):
        """
        :type n: int
        :rtype: int
        """
        if not n:
            return 0
            
        numOfTrees = [0] * (n+1)     # for easier indexing. Using numOfTrees[1:]
        numOfTrees[0] = 1
        
        for i in xrange(1, n+1):
            for j in xrange(1, i+1):
                numOfTrees[i] += numOfTrees[j-1] * numOfTrees[i-j] 
            
        return numOfTrees[n]

 

Idea

When you are given `n` (`n` is the size of sorted numbers to be placed in BST), there are multiple ways to construct unique BSTs depending on which element is placed as the root: you can put the first element as the root, then place the remaining `n-1` elements in the right tree. You can put the second element as the root, then place the first element as the left tree and the remaining `n-2` elements in the right tree. So on and so forth. 

Therefore, you can use an array, `numOfTrees` in my code, to store the number of unique BSTs. The final result, `numOfTrees[n]`, will be based on `numOfTrees[n’]` where `n’ < n`: You can put 1~n as root. When you put element `i` (`1<=i<=n`) as the root, its left tree can have `numOfTrees[i-1]` different unique ways of construction and its right tree can have `numOfTrees[n-i]` ways of construction. So the total number of unique trees when root equal to `i` is `numOfTrees[i-1] *numOfTrees[n-i]`.

A more mathematical way is to directly solve this problem using Catalan Number. Then you only need O(N) time and O(1) space. Please find introduction to Catalan Number below:

catalan 

Leetcode 97: Interleaving String

https://leetcode.com/problems/interleaving-string/

Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.

For example,
Given:
s1 = "aabcc",
s2 = "dbbca",

When s3 = "aadbbcbcac", return true.
When s3 = "aadbbbaccc", return false.

 

Code

class Solution(object):
    def isInterleave(self, s1, s2, s3):
        """
        :type s1: str
        :type s2: str
        :type s3: str
        :rtype: bool
        """
        if len(s1) + len(s2) != len(s3):
            return False
        if not s1:
            return s3 == s2
        if not s2:
            return s3 == s1
        
        res = [[False] * (len(s1)+1) for _ in xrange(len(s2)+1)]
        
        for i in xrange(len(s1)+1):
            res[0][i] = (s1[:i] == s3[:i])
        for j in xrange(len(s2)+1):
            res[j][0] = (s2[:j] == s3[:j])
        
        for j in xrange(1, len(s2)+1):
            for i in xrange(1, len(s1)+1):
                res[j][i] = (res[j][i-1] and (s3[i+j-1] == s1[i-1])) or (res[j-1][i] and (s3[i+j-1]==s2[j-1]))
        
        return res[-1][-1]
        

 

Idea

Use DP. `res[j][i]` is the boolean indicator of whether `s3[:i+j]` is an interleaving string of `s1[:i]` and `s2[:j]`. It can be written recursively as `res[j][i] = (res[j][i-1] and (s3[i+j-1] == s1[i-1])) or (res[j-1][i] and (s3[i+j-1]==s2[j-1]))`. 

 

Reference

http://tianmaying.com/tutorial/LC97

Leetcode 101: Symmetric Tree

https://leetcode.com/problems/symmetric-tree/

Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).

For example, this binary tree is symmetric:

    1
   / \
  2   2
 / \ / \
3  4 4  3

But the following is not:

    1
   / \
  2   2
   \   \
   3    3

Note:
Bonus points if you could solve it both recursively and iteratively.

confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.

 

Code

# 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 isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        return not root or self.dfs(root.left, root.right)
        
    def dfs(self, root1, root2):
        if (not root1 and root2) or (not root2 and root1):
            return False
        elif not root1 and not root2:
            return True
        elif root1.val == root2.val:
            return self.dfs(root1.left, root2.right) and self.dfs(root1.right, root2.left)
        else:
            return False

 

Idea

Maintain two pointers pointing to symmetric positions in the tree. If the two tree nodes being pointed to are not None and have same value, then recursively check if their children in the symmetric positions are the same. If the two tree nodes being pointed to are both None, it also indicates they are symmetric. 

Leetcode 7: Reverse Integer

https://leetcode.com/problems/reverse-integer/

Reverse digits of an integer.

Example1: x = 123, return 321
Example2: x = -123, return -321

click to show spoilers.

Have you thought about this?

Here are some good questions to ask before coding. Bonus points for you if you have already thought through this!

If the integer’s last digit is 0, what should the output be? ie, cases such as 10, 100.

Did you notice that the reversed integer might overflow? Assume the input is a 32-bit integer, then the reverse of 1000000003 overflows. How should you handle such cases?

For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows.

Update (2014-11-10):
Test cases had been added to test the overflow behavior.

 

Code

import re

class Solution(object):
    def reverse(self, x):
        """
        :type x: int
        :rtype: int
        """
        m = re.match('(^[\+\-]*)(\d+)', str(x))
        
        sign = 1
        if m and m.group(1):
            sign = -(ord(m.group(1)) - 44)         # '-' ascii: 45  '+' ascii: 43
        
        if m and m.group(2):
            num = int(m.group(2)[::-1])
            num = num * sign
            if num > 2147483647 or num < -2147483648:
                return 0
            return num
            
        return 0

 

Idea

Simply using regex to find the two parts in the original string: sign and digits. I am a little cheating by calling `int()` directly: it automatically handles the situations when `m.group(2)[::-1]` starts with multiple zeros.

Spoilers for the problem are really important. This is an easy problem but with some corner cases you need to consider.

Leetcode 8: String to Integer (atoi)

https://leetcode.com/problems/string-to-integer-atoi/

Implement atoi to convert a string to an integer.

Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.

Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.

Update (2015-02-10):
The signature of the C++ function had been updated. If you still see your function signature accepts a const char * argument, please click the reload button to reset your code definition.

spoilers alert… click to show requirements for atoi.

Requirements for atoi:

The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.

The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.

If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.

If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned.

 

Code

import re

class Solution(object):
    def myAtoi(self, str):
        """
        :type str: str
        :rtype: int
        """
        str = str.strip()
        str = re.findall("^[\+\-0]*\d+", str)
        
        try:
            num = int(''.join(str))
            if num > 2147483647:
                return 2147483647
            if num < -2147483648:
                return -2147483648
            return num
        except:
            return 0

 

Idea

`atoi` is a C library function that converts a string into an integer. Here I am using regex to find substring starting with +, – or 0 followed by multiple digits. Then just use `int()` to convert the string into integer.

 

 

 

Leetcode 25: Reverse Nodes in k-Group

https://leetcode.com/problems/reverse-nodes-in-k-group/

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.

You may not alter the values in the nodes, only nodes itself may be changed.

Only constant memory is allowed.

For example,
Given this linked list: 1->2->3->4->5

For k = 2, you should return: 2->1->4->3->5

For k = 3, you should return: 3->2->1->4->5

 

Code

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

class Solution(object):
    def rotate(self, pt1, k):
        '''
        # return:
        # pt1: the new head of the current k elements
        # pt2: the head of the next k elements
        # i: the number of elements just being rotated  
        '''
        i = 2
        pt2 = pt1.next        
        
        pt1.next = None
        while i<=k and pt2:
            pt3 = pt2.next
            pt2.next = pt1
            pt1 = pt2
            pt2 = pt3
            i += 1
        
        return pt1, pt2, i
            
    def reverseKGroup(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        if k == 1 or head is None or head.next is None:
            return head
        
        new_head = None
        tail = ListNode(999)  # tail is the last k elements's last element.
                              # Dummy at the beginning. 
        pt1 = head            

        while pt1:
            # pt1 will become the new head in the current k elements
            # pt2 will become the head of the next k elements
            pt1, pt2, i = self.rotate(pt1, k)
            
            # rotation reaches the end but the elements in the rotation are less than k
            if pt2 is None and i<=k:
                pt1, pt2, _ = self.rotate(pt1, k)
            
            if not new_head:
                new_head = pt1
            
            tail.next = pt1
            tail = head
            head = pt2
            
            # Set pt1 to be the new head in the next k elements
            pt1 = pt2
            
        return new_head

 

Idea

What I implemented is pretty straightforward in iterative way: find the first k elements and rotate them, then start to rotate the next k elements, so on so forth. When we reach the last k’ elements (k’ <= k), we need to check if we need to rotate them or not.

More trick way is to implement the solution in a recursive way (ref: https://leetcode.com/discuss/21301/short-but-recursive-java-code-with-comments):

public ListNode reverseKGroup(ListNode head, int k) {
    ListNode curr = head;
    int count = 0;
    while (curr != null && count != k) { // find the k+1 node
        curr = curr.next;
        count++;
    }
    if (count == k) { // if k+1 node is found
        curr = reverseKGroup(curr, k); // reverse list with k+1 node as head
        // head - head-pointer to direct part, 
        // curr - head-pointer to reversed part;
        while (count-- > 0) { // reverse current k-group: 
            ListNode tmp = head.next; // tmp - next head in direct part
            head.next = curr; // preappending "direct" head to the reversed list 
            curr = head; // move head of reversed part to a new node
            head = tmp; // move "direct" head to the next node in direct part
        }
        head = curr;
    }
    return head;
}

 

 

Leetcode 103: Binary Tree Zigzag Level Order Traversal

https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/

Given a binary tree, return the zigzag level order traversal of its nodes’ values. (ie, from left to right, then right to left for the next level and alternate between).

For example:
Given binary tree {3,9,20,#,#,15,7},

    3
   / \
  9  20
    /  \
   15   7

return its zigzag level order traversal as:

[
  [3],
  [20,9],
  [15,7]
]

confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.

 

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 *

class Solution(object):
    def zigzagLevelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        q = deque()
        q.append((root, 1))
        
        res = []
        while q:
            tup = q.popleft()
            n, l = tup[0], tup[1]
            if n is not None:
                if len(res) < l:
                    res.append([])
                if l % 2:
                    res[l-1].append(n.val)
                else:
                    res[l-1].insert(0, n.val)
                q.append((n.left, l+1))
                q.append((n.right, l+1))
        
        return res

 

Idea

Use BFS to traverse nodes. Note that there may be one performance issue in my code: at line 29, left appending new element to a list may cause the whole list being copied again. We can pre-allocate a list for nodes in the same depth when `len(res) < l` by using: `res.append([0]*(len(q)+1))`.

Leetcode 108: Convert Sorted Array to Binary Search Tree

https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/

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

 

Code

# 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
        """
        self.nums = nums
        return self.helper(0, len(nums))
    
    def helper(self, start, end):
        if end <= start:
            return None
        
        mid = start + (end-start)/2
        root = TreeNode(self.nums[mid])
        root.left = self.helper(start, mid)        
        root.right = self.helper(mid+1, end)
        return root

 

Idea

The same idea to https://czxttkl.com/?p=1366 but easier because you have full view of the whole list.