Monday, March 30, 2015

Number of 1 Bits

Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also known as the Hamming weight).
For example, the 32-bit integer ’11' has binary representation 00000000000000000000000000001011, so the function should return 3.
Solution1:
Run time complexity is O(n), constant space.
public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        if(n == 0) {
            return 0;
        }
        
        int count = 0;
        while(n != 0) {
            if((n & 1) == 1) {
                count++;
            }
            n = n >>> 1;  //unsigned right shift(强制补0)
        }
        
        return count;
    }
}
Solution2: 
The bitwise and of x with x − 1 differs from x only in zeroing out the least significant nonzero bit: subtracting 1 changes the rightmost string of 0s to 1s, and changes the rightmost 1 to a 0. If x originally had n bits that were 1, then after only n iterations of this operation, x will be reduced to zero
Run time complexity is O(n), n is number of 1s, constant space.
Check Hamming Weight on Wiki: http://en.wikipedia.org/wiki/Hamming_weight
public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        if(n == 0) {
            return 0;
        }
        
        int count = 0;
        while(n != 0) {
            n = (n & (n - 1));
            count++;
        }
        
        return count;
    }
}

Tuesday, March 24, 2015

Serialize and Deserialize 3-ray tree

A 3-ary tree is where every node has 3 children. Given a string of serialized tree, How to deserialze and serialize it? 

Solution:
import java.util.LinkedList;

public class SerializeDeserializeTree {
    public static void main(String[] args) {
  
        String tree = "1,1,2,3,1,2,3,1,#,#,#,#,3";
        TreeNode root = deserialize(tree);
  
        System.out.print("serializeTree: "+serializeTree(root));
  
    }
 
    public static class TreeNode {
        int val;
        TreeNode[] child;
        TreeNode(int x) {
            this.val = x;
            this.child = new TreeNode[3];
        }
    }
 
    public static int getDepth(TreeNode root) {
        if(root == null) {
            return 0;
        }
        return Math.max(Math.max(getDepth(root.child[0]), getDepth(root.child[1])), getDepth(root.child[2])) + 1;
    }
    
    //serialize
    public static String serializeTree(TreeNode root) {
        if(root == null) {
            return "#";
        }
  
        StringBuilder res = new StringBuilder();
        LinkedList queue = new LinkedList();
        int depth = getDepth(root);
        queue.add(root);
        res.append(root.val).append(",");
        int last = 1;
        int cur = 0; 
        int level = 1;
        while(!queue.isEmpty()) {
            TreeNode node = queue.poll();
            last--;
            if(node.child[0] != null) {
                res.append(node.child[0].val).append(",");
                queue.add(node.child[0]);
                cur++;
            }else if(level < depth){
                res.append("#").append(",");
            }
   
            if(node.child[1] != null) {
                res.append(node.child[1].val).append(",");
                queue.add(node.child[1]);
                cur++;
            }else if(level < depth){
                res.append("#").append(",");
            }
   
            if(node.child[2] != null) {
                res.append(node.child[2].val).append(",");
                queue.add(node.child[2]);
                cur++;
            }else if(level < depth){
                res.append("#").append(",");
            }
   
            if(last == 0 && !queue.isEmpty()) {
                last = cur;
                cur = 0;
                level++;
            } 
        }
        res = res.deleteCharAt(res.length() - 1);
        return res.toString();
   }
 
   //deserialize
   public static TreeNode deserialize(String tree) {
       if (tree == null || tree.length() == 0)
           return null;

       String[] nodes = tree.split(",");
       if (nodes[0] == "#")
           return null;

       TreeNode root = new TreeNode(Integer.parseInt(nodes[0]));
       LinkedList queue = new LinkedList();
       queue.add(root);
       for (int i = 1; i < nodes.length; i = i + 3) {
           TreeNode r = queue.poll();
           if (!nodes[i].equals("#")) {
               TreeNode n = new TreeNode(Integer.parseInt(nodes[i]));
               queue.add(n);
               r.child[0] = n;
           }
           if (!nodes[i + 1].equals("#")) {
               TreeNode n = new TreeNode(Integer.parseInt(nodes[i + 1]));
               queue.add(n);
               r.child[1] = n;
           }
           if(!nodes[i + 2].equals("#")) {
               TreeNode n = new TreeNode(Integer.parseInt(nodes[i + 2]));
               queue.add(n);
               r.child[2] = n;
           }
       }
  
       return root;
   }
}

Convert a string to binary int

Convert a string to binary int.
For example, string "foo", after convert "foo", the output should be 01100110 01101111 01101111.

Solution:

public static void convert(String str) {
    byte[] bytes = str.getBytes();
    StringBuilder binary = new StringBuilder();
    for(byte b : bytes) {
        int val = b;
        for(int i = 0; i < 8; i++) {
            if((val & 128) == 0) {
                binary.append(0);
            }else {
                binary.append(1);
            }
            val = (val << 1);
        }
        binary.append(" ");
    }
  
    System.out.println("'" + str + "' to binary: " + binary);
 }

Find most frequent word in a string

Find most frequent word in a string.
For example, "I have a dream and dream.Cool.", the most frequent word is "dream".

Solution:
1. split string with "." and " ";
2. store the splited string into a hashmap, key is the word, value is the number this word appears;
3. find the largest value.
public class MostFrequentWordInString {
    public static void main(String[] args) {
        String str = "I have.a dream and dream.Cool.";
        mostFrequentWord(str);
    }
 
    public static String mostFrequentWord(String str) {
        String[] lists = str.split("\\.| ");
  
        HashMap map = new HashMap();
        for(int i = 0; i < lists.length; i++) {
            if(!map.containsKey(lists[i])) {
                map.put(lists[i], 1);
            }else {
                map.put(lists[i], map.get(lists[i]) + 1);
            }
        }
  
        Map.Entry max = null;
        for(Map.Entry i : map.entrySet()) {
            if(max == null) {
                max = i;
            }
            if((int)i.getValue() > (int)max.getValue()) {
                max = i;
            }
        }
  
        System.out.println("Most frequent word is: " + (String)max.getKey());
        return (String)max.getKey();
    }
}

Single Number


Given an array of integers, every element appears twice except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
Solution1:  XOR
Run time complexity is O(n), constant space
public class Solution {
    public int singleNumber(int[] A) {
        int result = A[0];
        for(int i = 1; i < A.length; i++) {
            result = result ^ A[i];
        }
        return result;
    }
}

// 异或运算:a ^ a = 0, a ^ b ^ a = b
Solution2: bit operation
统计整数的每一位来得到出现次数。如果每个元素重复出现二次,那么每一位出现1的次数也会是2的倍数。统计完成后对每一位进行取余2,那么结果中就只剩下那个出现一次的元素。
只需要对数组进行一次线性扫描,统计完之后每一位进行取余2并且将位数字赋给结果整数。
Run time complexity is O(n), space complexity is O(32) = O(1), constant space.
public class Solution {
    public int singleNumber(int[] A) {
        if(A == null || A.length == 0) {
            return 0;
        }
        
        int[] digits = new int[32];
        for(int i = 0; i < 32; i++) {
            for(int j = 0; j < A.length; j++) {
                digits[i] += (A[j] >> i) & 1;
            }
        }
        
        int res = 0;
        for(int i = 0; i < 32; i++) {
            res += (digits[i] % 2) << i;
        }
        return res;
    }
}

Single Number II

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?
Solution1: HashMap
public class Solution {
    public int singleNumber(int[] A) {
        
        HashMap map = new HashMap();
        int i = 0;
        while( i < A.length){
            if(map.containsKey(A[i])){
                map.put(A[i], map.get(A[i])+1);
            }else{
                map.put(A[i], 1);
            }
            i++;
        }
        
        for(Integer key : map.keySet()){
            Integer val = map.get(key);
            if(val != 3) return key;
        }
        
        return 0;
    }
}
Solution2:
public class Solution {
    public int singleNumber(int[] A) {
        if( A.length == 1 ) return A[0];
        
        Arrays.sort(A);
        for( int i = 0 ; i + 2 < A.length; i = i + 3){
            if(A[i] == A[i+1] && A[i] == A[i+2]){
                continue;
            }else if( A[i] != A[i+1] ) return A[i];
        }
        
        return A[A.length - 1];
    }
}
Solution3: bit manipulation 
统计整数的每一位来得到出现次数。如果每个元素重复出现三次,那么每一位出现1的次数也会是3的倍数。统计完成后对每一位进行取余3,那么结果中就只剩下那个出现一次的元素。
只需要对数组进行一次线性扫描,统计完之后每一位进行取余3并且将位数字赋给结果整数,这是一个常量操作(因为整数的位数是固定32位),所以时间复杂度是O(n), constant space。
public class Solution {
    public int singleNumber(int[] A) {
        if(A == null || A.length == 0)
            return 0;
        
        int[] digits = new int[32];
        for(int i = 0; i < 32; i++) {
            for(int j = 0; j < A.length; j++) {
                digits[i] += (A[j] >> i) & 1;
            }
        }
        
        int res = 0;
        for(int i = 0; i < 32; i++) {
            res += (digits[i] % 3) << i;
        }
        return res;
    }
}

Reference: http://blog.csdn.net/linhuanmars/article/details/22645599

Sunday, March 22, 2015

Dining philosophers problem

"Five silent philosophers sit at a round table with bowls of spaghetti. Forks are placed between each pair of adjacent philosophers. 
Each philosopher must alternately think and eat. However, a philosopher can only eat spaghetti when he has both left and right forks. Each fork can be held by only one philosopher and so a philosopher can use the fork only if it is not being used by another philosopher. After he finishes eating, he needs to put down both forks so they become available to others. A philosopher can take the fork on his right or the one on his left as they become available, but cannot start eating before getting both of them.
Eating is not limited by the remaining amounts of spaghetti or stomach space; an infinite supply is assumed.
The problem is how to design a discipline of behavior (a concurrent algorithm) such that each philosopher will not starve; i.e., can forever continue to alternate between eating and thinking, assuming that any philosopher cannot know when others may want to eat or think. "
Check this on Wiki.
The problem was designed to illustrate the challenges of avoiding deadlock.
  • think until the left fork is available; when it is, pick it up;
  • think until the right fork is available; when it is, pick it up;
  • when both forks are held, eat for a fixed amount of time;
  • then, put the forks down;
  • repeat from the beginning.
Solution:
import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class DiningPhilosophers {
	// The number of philosophers
	private static final int numPhilosophers = 5;
	
	public static void main(String[] args) {
		// Model each fork with a lock
		Lock[] forks = new ReentrantLock[numPhilosophers];
		
		for(int i = 0; i < numPhilosophers; i++) {
			forks[i] = new ReentrantLock();
		}
		
		// Create the philosophers and start each running in its own thread.
		Philosopher[] philosophers = new Philosopher[numPhilosophers];
		
		for(int i = 0; i < numPhilosophers; i++) {
			philosophers[i] = new Philosopher(i, forks[i], forks[(i + 1) % numPhilosophers]);
			new Thread(philosophers[i]).start();
		}
		
	}
}

//A philosopher alternates between thinking and eating. To eat, the philosopher needs to pick
//up the left fork and then the right fork sequentially. The philosopher shares 
//forks with its neighbors, so it cannot eat at the same time as either neighbor
class Philosopher implements Runnable {
	// Used to vary how long a philosopher thinks before eating and how long the
	// philosopher eats
	private Random numGenerator = new Random();
	
	// The philosopher's unique id
	private int pid;
	
	// The forks this philosopher may use
	private Lock leftFork;
	private Lock rightFork;
	
	//Constructs a new philosopher
	public Philosopher(int pid, Lock leftFork, Lock rightFork) {
		this.pid = pid;
		this.leftFork = leftFork;
		this.rightFork = rightFork;
	}
	
	//Repeatedly think, pick up forks, eat and put down forks
	public void run() {
		try {
			while(true) {
				think();
				pickLeftFork();
				pickRightFork();
				eat();
				putDownForks();
			}	
		}catch (InterruptedException e) {
			System.out.println("Philosopher " + pid + " was interrupted.\n");
		}
	}
	
	//Let a random amount of time pass to model thinking. @throws InterruptedException
	private void think() throws InterruptedException {
		System.out.println("Philosopher " + pid + " is thinking.\n");
		System.out.flush();
		Thread.sleep (numGenerator.nextInt(10));
		
		/**
		 * With "Thread.sleep(10)", this can eliminates the possibility of deadlock 
		 * (the system can always advance to a different state) but still suffers from the problem of "livelock". 
		 * If all five philosophers appear in the dining room at exactly the same time and 
		 * each picks up the left fork at the same time the philosophers will wait ten milliseconds 
		 * until they all put their forks down and then wait a further ten milliseconds 
		 * before they all pick them up again.
		 */
		//Thread.sleep(10);  
	}
	
	//Locks the left fork to signify that this philosopher is holding it
	private void pickLeftFork() {
		leftFork.lock();
		System.out.println("Philosopher " + pid + " is holding left fork.\n");
		System.out.flush();
	}
	
	//Locks the right fork to signify that this philosopher is holding it
	private void pickRightFork() {
		rightFork.lock();
		System.out.println("Philosopher " + pid + " is holding right fork.\n");
		System.out.flush();
	}
	
	//Let a random amount of time pass to model eating. @throws InterruptedException
	private void eat() throws InterruptedException {
		System.out.println("Philosopher " + pid + " is eating.\n");
		System.out.flush();
		Thread.sleep (numGenerator.nextInt(10));
		//Thread.sleep(10);
	}
	
	//Releases the locks on both forks to model putting them down so the other philosophers can use them.
	private void putDownForks() {
		leftFork.unlock();
		rightFork.unlock();
		System.out.println("Philosopher " + pid + " puts down forks.\n");
	}
}

Reference: http://everythingcomputerscience.com/projects/java_programs/DiningPhilosophers.txt

Find email which exists in every list

Write a function that will take in email lists and return a new email list that contains only the email addresses that existed in all lists 鏉ユ簮涓€浜�.涓夊垎鍦拌鍧�. 
1: foo@amazon.combar@amazon.com. 1point 3acres 璁哄潧
2: bar@amazon.combar@amazon.com. visit 1point3acres.com for more.
o: bar@amazon.com

Solution:
Using two hashset, here are set1 and set2.
1. Store every email in list1 into set1;
2. Start from list2, if email is existed in set1, then add it into set2. After finishing traverse this list, clear set1, copy every email in set2 into set1, then clear set2. Move on to next list.
3. After traversing every list, set1 contains the email addresses that exist in every list. Just return set1.
Run time complexity is O(m * n), m is the number of lists, n is the number of email per list. Space complexity is O(n), n is number of email addresses in list1.
public static ArrayList existInAll(ArrayList> lists) throws Exception{
		if(lists == null) {
			return null;
		}
		
		HashSet set1 = new HashSet();
		HashSet set2 = new HashSet();
		
		for(int i = 0; i < lists.get(0).size(); i++) {
			String str = lists.get(0).get(i);
			set1.add(str);
		}
		
		for(int i = 1; i < lists.size(); i++) {
			for(int j = 0; j < lists.get(i).size(); j++) {
				String cur = lists.get(i).get(j);
				if(set1.contains(cur)) {
					set2.add(cur);
				}
			}
			set1.clear();
			Iterator iterator = set2.iterator();
			while(iterator.hasNext()) {
				set1.add((String)iterator.next());
			}
			set2.clear();
		}
		
		Iterator getRes = set1.iterator();
		ArrayList res = new ArrayList();
		while(getRes.hasNext()) {
			res.add((String)getRes.next());
		}
		
		if(res.size() == 0) {
			System.out.println("Can't find any email which exists in every list.");
		}else {
			for(String s : res) {
				System.out.println(s);
			}
		}
		
		return res;
	}

Saturday, March 21, 2015

Sudoku Solver

Write a program to solve a Sudoku puzzle by filling the empty cells.
Empty cells are indicated by the character '.'.
You may assume that there will be only one unique solution.
A sudoku puzzle...
...and its solution numbers marked in red.
Solution: 
类似N-Queens问题, 一个个尝试填数,不行就回溯,直到填满返回。
如果对一个格子尝试从0~9都不行,那么说明整个sudoku无解,返回false就好。
对整个棋盘所有'.'都填完了,那么就可以返回true了
public class Solution {
    public void solveSudoku(char[][] board) {
        if(board == null || board.length != 9|| board[0].length != 9) {
            return;
        }
        helper(board);
    }
    
    public boolean helper(char[][] board) {
        for(int i = 0; i < board.length; i++) {
            for(int j = 0; j < board[0].length; j++) {
                if(board[i][j] == '.') {
                    for(char c = '1'; c <= '9'; c++) {
                        if(isValid(board, i, j, c)) {  //try
                            board[i][j] = c;
                            if(helper(board)) {
                                return true;
                            }else {
                                board[i][j] = '.';  //go back
                            }
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    }
    
    public boolean isValid(char[][] board, int i, int j, int c) {
        for(int m = 0; m < 9; m++) {  //check row
            if(m != j && board[i][m] == c) {
                return false;
            }
        }
        
        for(int m = 0; m < 9; m++) {  //check column
            if(m != i && board[m][j] == c) {
                return false;
            }
        }
        
        for(int row = i/3*3; row < i/3*3+3; row++) {  //check sub-boxes
            for(int col = j/3*3; col < j/3*3+3; col++) {  
                if((row != i || col != j) && board[row][col] == c)  
                    return false;  
            }  
        }
        return true;
    }
}

Valid Sudoku

Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules.
The Sudoku board could be partially filled, where empty cells are filled with the character '.'.
A partially filled sudoku which is valid.
Note:
A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated.
Solution:
对于每一行,每一列,每个九宫格进行验证,总共需要27次验证,每次看九个元素。
时间复杂度就是O(3*n^2), n=9
public class Solution {
    public boolean isValidSudoku(char[][] board) {
        if(board == null || board.length != 9 || board[0].length != 9)
            return false;
        
        for(int i = 0; i < 9; i++) {  //check each row
            HashSet map = new HashSet();
            for(int j = 0; j < 9; j++) {
                if(!map.add(board[i][j]) && board[i][j] != '.') {
                    return false;
                }
            }
        }
        
        for(int i = 0; i < 9; i++) {  //check each column
            HashSet map = new HashSet();
            for(int j = 0; j < 9; j++) {
                if(!map.add(board[j][i]) && board[j][i] != '.') {
                    return false;
                }
            }
        }
        
        for(int i = 0; i < 3; i++) {  //check each 9 sub-boxes
            for(int j = 0; j < 3; j++) {
                HashSet map = new HashSet();
                for(int m = i * 3; m < i * 3 + 3; m++) {
                    for(int n = j * 3; n < j * 3 + 3; n++) {
                        if(!map.add(board[m][n]) && board[m][n] != '.') {
                            return false;    
                        }
                    }
                }
            }
        }
        return true;
    }
}

Implement BST Search

Search in a binary search tree.

Solution1: iterative
Run time complexity is O(logn), constant space.
//iterative
 public static boolean search(TreeNode root, int num) {
     if(root == null) {
         return false;
     }
  
     TreeNode node = root;
     while(node.val != num) {
         if(node.val < num) {
             node = node.right;
         }else {
             node = node.left;
         }
         if(node == null) {
             return false;
         }
     }
     return true;
 }

Solution2: recursion
Run time complexity is O(logn), stack space.
//recursion
 public static boolean searchRec(TreeNode root, int num) {
     if(root == null)
         return false;
  
     if(root.val == num)
         return true;
  
     if(root.val < num) {
         return searchRec(root.right, num);
     }else {
         return searchRec(root.left, num);
     }
 }

Shortest Path between Two Nodes

Given two nodes that are in a binary tree (this is guaranteed) find the shortest traversal path between them.
Solution1:
先用LCA找到ancestor,然后打印path。
public class TreeNode {
  int val;
  TreeNode left;
  TreeNode right;
  TreeNode(int x) { val = x; }
 } 
 
 public static List shortestPath(TreeNode root, TreeNode A, TreeNode B) {
  if(root == null) {
   return null;
  }
  
  Stack pathL = new Stack();
  Stack pathR = new Stack();
  
  TreeNode ancestor = lowestCommonAncestor(root, A, B);
  TreeNode node = ancestor;
  
  helper(node.left, A, B, pathL);
  helper(node.right, A, B, pathR);
  
  pathL.push(node);
  while(!pathR.isEmpty()) {
   pathL.push(pathR.pop());
  }
  
  for(TreeNode t: pathL) {
   System.out.print(t.val + " ");
  }

  return pathL;
 }
 
 public static boolean helper(TreeNode root, TreeNode A, TreeNode B, Stack path) {
  if(root == null) {
   return false;
  }

  if(root.val == A.val || root.val == B.val) {
   path.push(root);
   return true;
  }
  
  if (helper(root.left, A, B, path) ||  helper(root.right, A, B, path)) {  //DFS
      path.push(root);
      return true;
  }
  return false;
  
 }
 
 public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) {
  
  if(root == null) {
            return null;
        }
  
        if(root == A || root == B) {
         return root;
        }
        
         
        TreeNode left = lowestCommonAncestor(root.left, A, B);
        TreeNode right = lowestCommonAncestor(root.right, A, B);
        
        if(left != null && right != null) {  // if A and B are on both sides
            return root;
        }
         
        if(left != null) {  // either one of A,B is on one side OR A,B is not in L&R subtrees
            return left;
        }else {
            return right;
        }
    }
From Han Chen

Solution2:
package leetcode;

import java.util.*;
import java.lang.*;
import java.io.*;
  
class TreeNode {
      public int val;
      public TreeNode left, right;
      public TreeNode(int val) {
          this.val = val;
          this.left = this.right = null;
      }
  }
 
class Shibai
{
 public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) {
  if (A == root) {
 
   return root;
  }
 
  if (B == root) {
   return root;
  }
 
  if (root == null) return root;
 
  TreeNode left = lowestCommonAncestor(root.left,A,B);
        TreeNode right = lowestCommonAncestor(root.right,A,B);
 
        if (left == null && right == null) return null;
 
        if (left != null && right != null) {
 
            return root;
        }
 
        if (left != null) {
 
         return left;
        }else {
 
         return right;
        }
 
 }
 
 public static TreeNode p(TreeNode r, TreeNode t,List arr) {
  if (r == t || r == null) return r;
  TreeNode left = p(r.left,t,arr);
  TreeNode right = p(r.right,t,arr);
  if (left != null || right != null) {
   arr.add(r);
  }
 
  return left != null? left:right;
 }
 
 
 public static void main (String[] args) throws java.lang.Exception
 {
  // your code goes here
  TreeNode root1 = new TreeNode(1);
  TreeNode root2 = new TreeNode(2);
  TreeNode root3 = new TreeNode(3);
  TreeNode root4 = new TreeNode(4);
  TreeNode root5 = new TreeNode(5);
  TreeNode root6 = new TreeNode(6);
  TreeNode root7 = new TreeNode(7);
  TreeNode root8 = new TreeNode(8);
 
  root1.left = root2;
  root1.right = root3;
  root2.left = root4;
  root2.right = root5;
  root3.left = root6;
  root3.right = root7;
  root6.left = root8;
 
  List arr1 = new ArrayList();
  List arr2 = new ArrayList();
  TreeNode A = root4;
  TreeNode B = root8;
 
  TreeNode lca = lowestCommonAncestor(root1,A,B);
 
  //arr1.addAll(arr2);
  arr1.add(A);
  TreeNode t1 = p(lca,A,arr1);
 
  TreeNode t2 = p(lca,B,arr2);
  
  Collections.reverse(arr2);
  arr2.add(B);
  arr2.remove(0);

  for (int i = 0; i < arr1.size(); i++) {
   System.out.println(arr1.get(i).val);
  }
  System.out.println("-------");
  for (int i = 0; i < arr2.size(); i++) {
   System.out.println(arr2.get(i).val);
  }
 }
}
From Shibai

Thursday, March 19, 2015

Valid Parentheses

Given a string containing just the characters '('')''{''}''[' and ']', determine if the input string is valid.
The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.
Solution: stack
遇到左括号就入栈,遇到右括号查看栈顶左括号是否与当前右括号匹配,匹配继续,否则返回false。最后判断下stack是不是为空,不为空,返回false。
算法的时间复杂度是O(n),空间复杂度也是O(n)。
public class Solution {
    public boolean isValid(String s) {
        if (s == null || s.length() <= 1)
            return false;
        
        Stack brackets = new Stack();

        for(int i = 0; i < s.length(); i++) {
            char b = s.charAt(i);
            if(b == '(' || b == '{' || b == '[')
                brackets.push(b);
            else if(b == ')' || b == '}' || b == ']') {
                if(brackets.size() == 0)
                    return false;
                
                if(b == ')' && brackets.peek() == '(')
                    brackets.pop();
                else if(b == '}' && brackets.peek() == '{')
                    brackets.pop();
                else if(b == ']' && brackets.peek() == '[')
                    brackets.pop();
                else 
                    return false;               
            }
        }
        
        if(brackets.size() == 0)
            return true;
        else
            return false;
    }
}

Multiply Strings

Given two numbers represented as strings, return multiplication of the numbers as a string.
Note: The numbers can be arbitrarily large and are non-negative.
Solution:
1 翻转string
2 建立数组,双层循环遍历两个string,把单位的乘积累加到数组相应的位置
3 处理进位并输出
4 注意前导零的corner case
public class Solution {
    public String multiply(String num1, String num2) {
        //reverse the string first
        String n1 = new StringBuilder(num1).reverse().toString();
        String n2 = new StringBuilder(num2).reverse().toString();
        
        //res is for storing the result of multiply
        int[] res = new int[n1.length() + n2.length()];
        
        for(int i = 0; i < n1.length(); i++) {
            for(int j = 0; j < n2.length(); j++) {
                //count the result at right place
                res[i + j] += (n1.charAt(i) - '0') * (n2.charAt(j) - '0');
            }
        }
        
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < res.length; i++) {
            int digit = res[i] % 10;  //for current position
            int carry = res[i] / 10;  //for carry
            if(i + 1 < res.length) {
                res[i + 1] += carry;
            }
            sb.insert(0, digit);  //prepend
        }
        
        while(sb.charAt(0) == '0' && sb.length() > 1) {
            sb.deleteCharAt(0);  //delete 0 at ahead
        } 
        
        return sb.toString();
    }
}

First Missing Positive

Given an unsorted integer array, find the first missing positive integer.
For example,
Given [1,2,0] return 3,
and [3,4,-1,1] return 2.
Your algorithm should run in O(n) time and uses constant space.
Solution: Counting sort
跟Counting sort一样,利用数组的index来作为数字本身的索引,把正数按照递增顺序依次放到数组中。即让A[0]=1, A[1]=2, A[2]=3, ... ,如果哪个数组元素违反了A[i]=i+1即说明i+1就是我们要求的第一个缺失的正数
对于不在范围内的数字,直接跳过,比如说负数,0,或者超过数组长度的正数, 或者当前的数字所对应的下标已经是对应数字
扫描数组两遍,时间复杂度是O(2*n)=O(n),而且利用数组本身空间,只需要一个额外变量,所以空间复杂度是O(1)。
public class Solution {
    public int firstMissingPositive(int[] A) {
        if(A == null || A.length == 0)
            return 1;
        
        for(int i = 0; i < A.length; i++) {
            // 如果A[i]超出范围,负数或0,下标和值对应,都跳过
            if(A[i] <= A.length && A[i] > 0 && A[A[i] - 1] != A[i]) {
                int temp = A[A[i] - 1];
                A[A[i] - 1] = A[i];
                A[i] = temp;
                i--;
            }
        }
        
        for(int i = 0; i < A.length; i++) {
            if(A[i] != i + 1) {
                return i + 1;
            }
        }
        return A.length + 1;
    }
}

Reference: http://blog.csdn.net/linhuanmars/article/details/20884585

Print all nodes at distance k from a given node

Given a binary tree, a target node in the binary tree, and an integer value k, print all the nodes that are at distance k from the given target node. No parent pointers are available.
BinaryTree
Consider the tree shown in diagram

Input: target = pointer to node with data 8. 
       root = pointer to node with data 20.
       k = 2.
Output : 10 14 22

If target is 14 and k is 3, then output 
should be "4 20"



Reference: http://www.geeksforgeeks.org/print-nodes-distance-k-given-node-binary-tree/
Solution:
Two types of nodes to be considered.
1) Nodes in the subtree rooted with target node. For example if the target node is 8 and k is 2, then such nodes are 10 and 14. 
Traverse subtrees rooted with the target node and decrement k in recursive call. When the k becomes 0, print the node currently being traversed.
2) Other nodes, may be an ancestor of target, or a node in some other subtree. For target node 8 and k is 2, the node 22 comes in this category.
For the output nodes not lying in the subtree with the target node as the root, we must go through all ancestors. For every ancestor, we find its distance from target node, let the distance be d, now we go to other subtree (if target was found in left subtree, then we go to right subtree) of the ancestor and find all nodes at k-d distance from the ancestor.
Time Complexity is O(n).
public class TreeNode {
  int val;
  TreeNode left;
  TreeNode right;
  TreeNode(int x) { val = x; }
 }
 
 //Recursive function to print all the nodes at distance k in the tree (or subtree) rooted with given root.
 public static void printKthDown(TreeNode node, int k) {
     if(node == null || k < 0) {  //base case
         return;
     }
  
     if(k == 0) {  //If we reach a k distant node, print it
         System.out.println(node.val);
         return;
     }
   
     // Recur for left and right subtrees
     printKthDown(node.left, k - 1);
     printKthDown(node.right, k - 1);
 }
 
 // Prints all nodes at distance k from a given target node.
 // The k distant nodes may be upward or downward.  This function
 // Returns distance of root from target node, it returns -1 if target
 // node is not present in tree rooted with root.
 public static int printKthDistanceNode(TreeNode root, TreeNode target, int k) {
     if(root == null) {  // Base Case 1: If tree is empty, return -1
        return -1;
     }
    
     // If target is same as root.  Use the downward function
     // to print all nodes at distance k in subtree rooted with
     // target or root
     if(root == target) {
         printKthDown(root, k);
         return 0;
     }
  
     int leftDistance = printKthDistanceNode(root.left, target, k);  // Recur for left subtree
  
     if(leftDistance != -1) {
         // If root is at distance k from target, print root
         // Note that leftDistance is Distance of root's left child from target
         if(leftDistance + 1 == k) {
             System.out.println(root.val);
         }else {  //go to right subtree and print all k-leftDistance-2 distant nodes. Note that the right child is 2 edges away from left child
             printKthDown(root.right, k - leftDistance - 2);
         }
         return leftDistance + 1; // Add 1 to the distance and return value for parent calls
     }
  
     int rightDistance = printKthDistanceNode(root.right, target, k);
  
     if(rightDistance != -1) {
         if(rightDistance + 1 == k) {
             System.out.println(root.val);
         }else {
             printKthDown(root.left, k - rightDistance - 2);
         }
         return rightDistance + 1;
     }
  
     return -1;  // If target was neither present in left nor in right subtree
 }
完整代码:
package leetcode;

public class PrintAllNodeAtDistanceKFromANode {
 
 public class TreeNode {
  int val;
  TreeNode left;
  TreeNode right;
  TreeNode(int x) { val = x; }
 }
 
 //Recursive function to print all the nodes at distance k in the tree (or subtree) rooted with given root.
 public static void printKthDown(TreeNode node, int k) {
  if(node == null || k < 0) {  //base case
   return;
  }
  
  if(k == 0) {  //If we reach a k distant node, print it
   System.out.println(node.val);
   return;
  }
  
  // Recur for left and right subtrees
  printKthDown(node.left, k - 1);
  printKthDown(node.right, k - 1);
 }
 
 // Prints all nodes at distance k from a given target node.
 // The k distant nodes may be upward or downward.  This function
 // Returns distance of root from target node, it returns -1 if target
 // node is not present in tree rooted with root.
 public static int printKthDistanceNode(TreeNode root, TreeNode target, int k) {
  if(root == null) {  // Base Case 1: If tree is empty, return -1
   return -1;
  }
  
  // If target is same as root.  Use the downward function
     // to print all nodes at distance k in subtree rooted with
     // target or root
  if(root == target) {
   printKthDown(root, k);
   return 0;
  }
  
  int leftDistance = printKthDistanceNode(root.left, target, k);  // Recur for left subtree
  
  if(leftDistance != -1) {
   // If root is at distance k from target, print root
         // Note that leftDistance is Distance of root's left child from target
   if(leftDistance + 1 == k) {
    System.out.println(root.val);
   }else {  //go to right subtree and print all k-leftDistance-2 distant nodes. Note that the right child is 2 edges away from left child
    printKthDown(root.right, k - leftDistance - 2);
   }
   return leftDistance + 1; // Add 1 to the distance and return value for parent calls
  }
  
  int rightDistance = printKthDistanceNode(root.right, target, k);
  
  if(rightDistance != -1) {
   if(rightDistance + 1 == k) {
    System.out.println(root.val);
   }else {
    printKthDown(root.left, k - rightDistance - 2);
   }
   return rightDistance + 1;
  }
  
  return -1;  // If target was neither present in left nor in right subtree
 }
 
 //create a new binary tree node
 TreeNode newNode(int data) {
  TreeNode temp = new TreeNode(data);
  temp.val = data;
  temp.left = temp.right = null;
  return temp;
 }
 
 public static void main(String[] args) {
  PrintAllNodeAtDistanceKFromANode p = new PrintAllNodeAtDistanceKFromANode();
  TreeNode root = p.newNode(20);
     root.left = p.newNode(8);
     root.right = p.newNode(22);
     root.left.left = p.newNode(4);
     root.left.right = p.newNode(12);
     root.left.right.left = p.newNode(10);
     root.left.right.right = p.newNode(14);
     
     TreeNode target = root.left.right;
     int k = 2;
     printKthDistanceNode(root, target, k);
     
 }
}

Wednesday, March 18, 2015

Find Nth Prime Number

Find Nth Prime Number.
For example,
First One Hundred Primes:
2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113
127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199 211 223 227 229
233 239 241 251 257 263 269 271 277 281
283 293 307 311 313 317 331 337 347 349
353 359 367 373 379 383 389 397 401 409
419 421 431 433 439 443 449 457 461 463
467 479 487 491 499 503 509 521 523 541
Solution:
public static boolean isPrime(int n) {
  for(int i = 2; i <= Math.sqrt(n); i++) {
      if(n % i == 0) {
          return false;
      }
  }
      return true;
 }
 
 public static void printPrime(int n) {
     int count = 0;
     for(int i = 2; i < Integer.MAX_VALUE; i++) {
        if(isPrime(i)) {
            System.out.println(i);
            count++;
        }
        if(count == n) {
            break;
        }
     }
 }

Check permutations

Determine if two strings are permutations of each other.

Solution:
先把string转换成char[ ],  然后sort,如果sort后是一样的,说明是permutation。
public static void main(String[] args) {
  String str1 = "1234";
  String str2 = "4231";
  String str3 = "";
  String str4 = "1235";
  System.out.println("check str1 & str2: "+checkPermutations(str1, str2));
  System.out.println("check str1 & str3: "+checkPermutations(str1, str3));
  System.out.println("check str1 & str4: "+checkPermutations(str1, str4));

 }
 
 public static boolean checkPermutations(String str1, String str2) {
  char[] c1 = str1.toCharArray();
  char[] c2 = str2.toCharArray();
  
  Arrays.sort(c1);
  Arrays.sort(c2);
  
  return Arrays.equals(c1, c2);
 }

Permutations II

Given a collection of numbers that might contain duplicates, return all possible unique permutations.
For example,
[1,1,2] have the following unique permutations:
[1,1,2][1,2,1], and [2,1,1].
Solution:
这个题跟Permutations非常类似,唯一的区别就是在这个题目中元素集合可以出现重复。这给我们带来一个问题就是如果不对重复元素加以区别,那么类似于{1,1,2}这样的例子我们会有重复结果出现。那么如何避免这种重复呢?方法就是对于重复的元素循环时跳过递归函数的调用,只对第一个未被使用的进行递归,我们那么这一次结果会出现在第一个的递归函数结果中,而后面重复的会被略过。如果第一个重复元素前面的元素还没在当前结果中,那么我们不需要进行递归。想明白了这一点,代码其实很好修改。首先我们要对元素集合排序,从而让重复元素相邻,接下来就是一行代码对于重复元素和前面元素使用情况的判断即可。
Reference: http://blog.csdn.net/linhuanmars/article/details/21570835
public class Solution {
    public ArrayList> permuteUnique(int[] num) {
        ArrayList> res = new ArrayList>();
        if(num == null || num.length == 0)
            return res;
        
        Arrays.sort(num);
        boolean[] used = new boolean[num.length];
        ArrayList list = new ArrayList();
        helper(num, res, list, used);
        return res;
    }
    
    public void helper(int[] num, ArrayList> res, ArrayList list, boolean[] used) {
        if(list.size() == num.length) {
            res.add(new ArrayList (list));
            return;
        }
        
        for(int i = 0; i < num.length; i++) {
            if(i > 0 && !used[i - 1] && num[i] == num[i - 1])
                continue;
            if(!used[i]) {
                used[i] = true;
                list.add(num[i]);
                helper(num, res, list, used);
                list.remove(list.size() - 1);
                used[i] = false;
            }
        }
    }
}

Permutations

Given a collection of numbers, return all possible permutations.
For example,
[1,2,3] have the following permutations:
[1,2,3][1,3,2][2,1,3][2,3,1][3,1,2], and [3,2,1].
Solution: 排列组合 -> 循环+递归
这道题跟N-QueensSudoku SolverCombination SumCombinations等一样,也是一个NP问题。方法还是原来那个套路,还是用一个循环递归处理子问题。区别是这里并不是一直往后推进的,前面的数有可能放到后面,所以我们需要维护一个used数组来表示该元素是否已经在当前结果中,因为每次我们取一个元素放入结果,然后递归剩下的元素,所以不会出现重复。时间复杂度还是NP问题的指数量级。
Reference: http://blog.csdn.net/linhuanmars/article/details/21569031
public class Solution {
    public ArrayList> permute(int[] num) {
        ArrayList> list = new ArrayList>();
        if(num == null || num.length == 0) 
            return list;
            
        boolean[] used = new boolean[num.length];
        ArrayList cur = new ArrayList();
        select(num, cur, list, used);
        return list;
    }
    
    public void select(int[] num, ArrayList cur, ArrayList> list, boolean[] used) {
        if(cur.size() == num.length) {
            list.add(new ArrayList(cur));
        }
        
        for(int i = 0; i < num.length; i++) {
            if(!used[i]) {
                used[i] = true;
                cur.add(num[i]);
                select(num, cur, list, used);
                
                //after completing a permutation, remove the elements
                cur.remove(cur.size() - 1);  
                used[i] = false;
            }
        }
    }
}