Leetcode-Serialize and Deserialize Binary Tree(Java)

Question:

Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.

Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.

For example, you may serialize the following tree

  1
 / \
2   3
   / \
  4   5

as “[1,2,3,null,null,4,5]”, just the same as how LeetCode OJ serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.
Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.

Thinking:

There are serveral thinkings emerged in my mind when I first saw this question. Firstly, I want to finishi the normal method which is the same as the Leetcode presenting. But it is LTE. Then I searched on the Internet and found my solution’s lack and then solved it.

Solution:

Previous Code:

//normal method
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
    String res = "";
    if (root == null)
        return res;
    Queue<TreeNode> q = new LinkedList<TreeNode>();
    q.add(root);
    res += root.val + ",";
    while (!q.isEmpty()){
        int num = q.size();
        String nullstr = "";
        while (num > 0){
            TreeNode n = q.poll();
            if (n.left != null){
                q.add(n.left);
                res += nullstr + n.left.val + ",";
            }
            else{
                nullstr += "null,";
            }
            if (n.right != null){
                q.add(n.right);
                res += nullstr + n.right.val + ",";
            }
            else{
                nullstr += "null,";
            }
            num--;
        }
    }

    return res;
}

// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
    TreeNode root;
    if(data.length() == 0)
        return null;
    String[] strs = data.split(",");
    root = new TreeNode(Integer.parseInt(strs[0]));
    bfs(root, strs, 1, true);
    bfs(root, strs, 2, false);

    return root;
}
private void bfs(TreeNode node, String[] strs, int index, boolean left){
    if (index >= strs.length)
        return;
    if (strs[index].equals("null"))
        return;
    TreeNode newNode = new TreeNode(Integer.parseInt(strs[index]));
    if (left){
        node.left = newNode;
    }
    else{
        node.right = newNode;
    }
    bfs(newNode, strs, index*2+1, true);
    bfs(newNode, strs, index*2+2, false);
}

Reference Code(http://blog.csdn.net/ljiabin/article/details/49474445):

public String serialize(TreeNode root) {
    StringBuilder sb = new StringBuilder();

    Queue<TreeNode> queue = new LinkedList<TreeNode>();
    queue.offer(root);

    while (!queue.isEmpty()) {
        TreeNode node = queue.poll();
        if (node == null) {
            sb.append("null,");
        } else {
            sb.append(String.valueOf(node.val) + ",");
            queue.offer(node.left);
            queue.offer(node.right);
        }
    }

    return sb.toString();
}

// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
    if (data.isEmpty()) return null;

    String[] vals = data.split(",");
    int[] nums = new int[vals.length];
    TreeNode[] nodes = new TreeNode[vals.length];

    for (int i = 0; i < vals.length; i++) {
        if (i > 0) {
            nums[i] = nums[i - 1];
        }
        if (vals[i].equals("null")) {
            nodes[i] = null;
            nums[i]++;
        } else {
            nodes[i] = new TreeNode(Integer.parseInt(vals[i]));
        }
    }

    for (int i = 0; i < vals.length; i++) {
        if (nodes[i] == null) {
            continue;
        }
        nodes[i].left = nodes[2 * (i - nums[i]) + 1];
        nodes[i].right = nodes[2 * (i - nums[i]) + 2];
    }

    return nodes[0];
}

}

Leetcode-Remove Duplicates from Sorted List II(Java)

Question:

Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.

For example,
Given 1->2->3->3->4->4->5, return 1->2->5.
Given 1->1->1->2->3, return 2->3.

Thinking:

It’s similar with other linked list question. We should build a dummy node before the head. Hold three pointers to operate the next pointer of these nodes.

Solution:

public ListNode deleteDuplicates(ListNode head) {
    if (head == null)
        return head;
    ListNode dummy = new ListNode(head.val-1);
    dummy.next = head;
    ListNode pre = dummy;
    ListNode p = head;
    ListNode next = head.next;
    while (next != null){
        if (p.val == next.val){
            while (next != null && p.val == next.val){
                next = next.next;
            }
            pre.next = next;
            if (next == null){
                break;
            } else{
                p = next;
                next = next.next;
            }
        } else{
            pre = p;
            p = p.next;
            next = next.next;
        }
    }

    return dummy.next;
}

Leetcode-Group Anagrams(Java)

Question:

Given an array of strings, group anagrams together.

For example, given: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”],
Return:

[
  ["ate", "eat","tea"],
  ["nat","tan"],
  ["bat"]
]

Note:
For the return value, each inner list’s elements must follow the lexicographic order.
All inputs will be in lower-case.

Thinking:

This question took me a lot of time. First, I want to get a String from the list, and check its anagrams with the rest of the list. And write the algorithm about the anagrams check. But time exceed. Then I try to change my thinking mode of this problem. We should consider the whole String as a element, and if two strings are anagrams, their new string with sorting are the same. So if we use a hashmap to store its previous string and sorted string, the problem will be easy to solve. So we build a hashmap, its key is the string element from the list, and its value is a new list which contains its key’s anagrams. Finally, we get the results from the hashmap and sort them by Collections.sort method.

Solution:

public List<List<String>> groupAnagrams(String[] strs) {
    int count = strs.length;
    List<List<String>> res = new ArrayList<List<String>>();
    if (count == 0)
        return res;
    HashMap<String, List<String>> hash = new HashMap<String, List<String>>();

    for (String str: strs){
        char[] ca = str.toCharArray();
        Arrays.sort(ca);
        String temp = new String(ca);
        if (hash.containsKey(temp)){
            hash.get(temp).add(str);
        }else{
            List<String> tempres = new ArrayList<String>();
            tempres.add(str);
            hash.put(temp, tempres);
        }
    }

    for (List<String> l: hash.values()){
        Collections.sort(l);
        res.add(l);
    }

    return res;
}

Reference:https://en.wikipedia.org/wiki/Anagram
http://javaconceptoftheday.com/anagram-program-in-java/
http://www.cnblogs.com/springfor/p/3874667.html

Leetcode-Number of Islands(Java)

Question:

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

Thinking:

If we find a island that we didn’t find before, we will use DFS or BFS find the whole land and change its value which will avoid find it again next time.

Solution:

private int m, n;

public int numIslands(char[][] grid) {
    m = grid.length;
    if (m == 0) return 0;
    n = grid[0].length;
    if (n == 0) return 0;

    int ans = 0;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (grid[i][j] != '1') continue;

            ans++;
            dfs(grid, i, j);
        }
    }
    return ans;
}


public void dfs(char[][] grid, int i, int j) {
    if (i < 0 || i >= m || j < 0 || j >= n) return;

    if (grid[i][j] == '1') {
        grid[i][j] = '2';
        dfs(grid, i - 1, j);
        dfs(grid, i + 1, j);
        dfs(grid, i, j - 1);
        dfs(grid, i, j + 1);
    }
}

Reference: http://blog.csdn.net/ljiabin/article/details/44975717

My Stupid Solution::

int res = 0;
public int numIslands(char[][] grid) {
    int rl = grid.length;
    if (rl == 0)
        return 0;
    int cl = grid[0].length;
    int[][] record = new int[rl][cl];
    int[][] visited = new int[rl][cl];


    for (int i = 0; i < rl; i++) {
        for (int j = 0; j < cl; j++) {
            dfsCheck(i, j, grid, record, visited);
        }
    }
    return res;
}

private void dfsCheck(int m, int n, char[][] grid, int[][] record, int[][] visited){
    if (visited[m][n] == 1)
        return;
    visited[m][n] = 1;
    int flag = 0;
    if (grid[m][n] == '1'){
        if (record[m][n] == 0){
            for (int i = -1; i < 2; i++){
                for (int j = -1; j < 2; j++){
                    if (m+i>=0 && m+i <grid.length && n+j>=0 && n+j<grid[0].length && (i+j == -1 || i+j == 1)){
                        if (record[m+i][n+j] != 0){
                            record[m][n] = record[m+i][n+j];
                            flag = 1;
                        }
                    }
                }
            }
            if (flag == 0)
                record[m][n] = ++res;
        }

        //extension
        for (int i = -1; i < 2; i++){
            for (int j = -1; j < 2; j++){
                if (m+i>=0 && m+i <grid.length && n+j>=0 && n+j<grid[0].length && (i+j == -1 || i+j == 1)){
                    if (grid[m+i][n+j] == '1' && visited[m+i][n+j] == 0)
                        dfsCheck(m+i, n+j, grid, record, visited);
                }
            }
        }
    }
}

Leetcode-Gas Station(Java)

Question:

There are N gas stations along a circular route, where the amount of gas at station i is gas[i].

You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations.

Return the starting gas station’s index if you can travel around the circuit once, otherwise return -1.

Note:
The solution is guaranteed to be unique.

Thinking:

Nomally, it can be sovled in n^2 time complexity, check every station whether it is possible. But it will be LTE, so we need a greedy method to sovle this problem. In fact, if previous result of total gas is larger than 0, and current gas station don’t meet the needs, it means all of the previous gas station is not valid. What’s more, it assumes there is only one solution, so what we need to do is to record the fisrt valid station index. In order to check whether it is valid, we also need another variable total to determine whether the set is valid.

Solution1:(LTM)

public int canCompleteCircuit1(int[] gas, int[] cost) {
    int len = gas.length;

    for (int i = 0; i < len; i++){
        int curGas = 0;
        for (int j = i; ; j++){
            curGas += gas[j%len];
            curGas -= cost[j%len];
            if (curGas < 0)
                break;
            if (j - len == i - 1){
                return i;
            }
        }
    }

    return -1;
}

Solution2:(Greedy)

public int canCompleteCircuit(int[] gas, int[] cost) {
    int len = gas.length;
    int curSum = 0;
    int total = 0;
    int index = 0;

    for (int i = 0; i < len; i++){
        curSum += gas[i] - cost[i];
        total += gas[i] - cost[i];
        if (curSum < 0){
            curSum = 0;
            index = i + 1;
        }
    }
    if (total < 0)
        return -1;
    else
        return index;

}