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