Saturday, April 6, 2013

Maximum Contiguous Subsequence Sum of At Least Length L.

Given a sequence of n real numbers A(1) ... A(n), determine a contiguous subsequence A(i) ... A(j) of length atleast L for which the sum of elements in the subsequence is maximized.

Set sumL to the sum of the first L array elements.
Set runningSum = sumL.
Set maxSum = sumL
For k = L + 1 up to n, the length of the array:
Set sumL = sumL + A(k) - A(k - L)
Set runningSum = max(runningSum + A(k), sumL)
Set maxSum = max(maxSum, runningSum)
Output maxSum

public class MaxContSumL {
public static void main(String[] args) {
int[] A = { 0, 5, -3, -1, 2, -4, -1, 7, 8 };
int L = 2;
maxContiguousSumOfLenAtleastL(A, L);

int[] B = { -5, -1, 2, -3, 0, -3, 3, };
L = 3;
maxContiguousSumOfLenAtleastL(B, L);
}

public static void maxContiguousSumOfLenAtleastL(int[] A, int L) {
int len = A.length;
int sumL = 0;
for (int i = 0; i < L; i++) {
sumL += A[i];
}
int runningSum = sumL;
int maxSum = sumL;
int start = 0, finish = 0;
for (int i = L; i < len; i++) {
sumL += (A[i] - A[i - L]);
runningSum = Math.max(runningSum + A[i], sumL);

if (runningSum > maxSum) {
maxSum = runningSum;
start = i - L + 1;
finish = i;
}
}

System.out.println("Max sum: " + maxSum);
System.out.println("Indices: i=" + start + " : j=" + finish);
}
}

Largest rectangle area in histogram

Given an array of positive integers that represent the bars in a histogram,
find the rectangle with the largest area under the curve and above the axis

import java.util.Stack;

public class Histogram {
public static void main(String[] args) {
int[] A = { 4, 1, 6, 3, 4, 7, 5, 2 };
int area = largestRectangleArea(A);

System.out
.println("reactange with largest area under the curve and above the axis: "
+ area);
}

public static int largestRectangleArea(int[] height) {

Stack<Integer> stack = new Stack<Integer>();
int i = 0, max = 0;
while (i < height.length) {
if (stack.isEmpty() || height[stack.peek()] <= height[i])
stack.push(i++);
else
max = Math.max(max, height[stack.pop()]
* (stack.isEmpty() ? i : i - stack.peek() - 1));
}
while (!stack.isEmpty())
max = Math.max(max, height[stack.pop()]
* (stack.isEmpty() ? i : i - stack.peek() - 1));
return max;
}

}

Print 2 BSTs in ascending order

Give two binary search trees, print the numbers of both together in ascending order.

import java.util.Random;
import java.util.Stack;

public class BST {
public static Node root1 = null;
public static Node root2 = null;
public static final int N = 7;
public static final int RANGE = 100;

public static void main(String[] args) {
System.out.println("Building first BST with values:");
root1 = buildBST(root1);

System.out.println("Building second BST with values:");
root2 = buildBST(root2);

System.out.println("printing 2 BSTs in ascending order: ");
printTwoBSTsInorder(root1, root2);
}

public static void printTwoBSTsInorder(Node r1, Node r2) {
Stack<Node> stk1 = new Stack<Node>();
Stack<Node> stk2 = new Stack<Node>();
boolean isFinished = false;
while (!isFinished) {
if (r1 != null && r2 != null) {
stk1.push(r1);
r1 = r1.left;
stk2.push(r2);
r2 = r2.left;
} else if (r1 != null && r2 == null) {
stk1.push(r1);
r1 = r1.left;
} else if (r1 == null && r2 != null) {
stk2.push(r2);
r2 = r2.left;
} else if (r1 == null && r2 == null) {
if (!stk1.isEmpty() && stk2.isEmpty()) {
r1 = stk1.pop();
System.out.print(r1.data + " ");
r1 = r1.right;
} else if (stk1.isEmpty() && !stk2.isEmpty()) {
r2 = stk2.pop();
System.out.print(r2.data + " ");
r2 = r2.right;
} else if (!stk1.isEmpty() && !stk2.isEmpty()) {
if (stk1.peek().data <= stk2.peek().data) {
r1 = stk1.pop();
System.out.print(r1.data + " ");
r1 = r1.right;
} else {
r2 = stk2.pop();
System.out.print(r2.data + " ");
r2 = r2.right;
}
} else {
isFinished = true;
}
}
}
}

public static Node buildBST(Node node) {
Random rand = new Random();

for (int i = 0; i < N; i++) {
int value = rand.nextInt(99) + 1;
System.out.print(value + " ");
node = insertIntoBST(node, value);
}
System.out.println();
return node;
}

public static Node insertIntoBST(Node node, int value) {
if (null == node) {
return new Node(value);
}
if (value <= node.data) {
node.left = insertIntoBST(node.left, value);
} else {
node.right = insertIntoBST(node.right, value);
}
return node;
}
}

class Node {
int data;
Node left;
Node right;

public Node(int data) {
this.data = data;
this.left = null;
this.right = null;
}
}

Given an int array which might contain duplicates, find if it is a sequence.

Given an int array which might contain duplicates, find if it is a sequence. 
Eg. {45,50,47,46,49,48}
is a sequence 45, 46,47,48,49,50
Sorting is an obvious solution. Can this be done in O(n) time and O(1) space

Approach:
Example array: A = {4, 1, 3, 3, 2}
1. get the min and max.
min=1 and max=4
2. if (max - min) > A.length then "its NOT a sequence".
3. else for each element in A[i] do the following:
a. calculate A[i] - min till A[i]-min=i;
i=0; 4 - 1 = 3, swap A[0] and A[3]
Now we have A = {3, 1, 3, 4, 2}
Again, 
i=0; 3 - 1 = 2, now A[0] and A[2] are same so swap A[0] and A[length-1] and put A[length] = infinite.
A = {2, 1, 3, 4, INF}
Again,
i=0; 2 - 1 = 1, swap A[0] and A[1], 
A = {1, 2, 3, 4, INF}
i=1; 2 - 1 = 1 (which is same as i)
similarlty for i=2, i=3
finally we have A as,
A = {1, 2, 3, 4, INF}

public class ArraySeq {
public static void main(String[] args) {
int[] A = { 45, 50, 47, 45, 50, 46, 49, 48, 49 };
System.out.println("Printing Original Array ...");
printArr(A);
System.out.println("Is Sequence: " + isSequence(A));

}

public static boolean isSequence(int[] A) {
int len = A.length;
int MIN = Integer.MAX_VALUE;
int MAX = Integer.MIN_VALUE;
boolean result = false;
for (int i = 0; i < len; i++) {
if (A[i] < MIN) {
MIN = A[i];
}
if (A[i] > MAX) {
MAX = A[i];
}
}
System.out.println("MIN:" + MIN + " " + "MAX:" + MAX);
if ((MAX - MIN) >= len) {
return result;
}
int i = 0;
while (i < len) {
while ((i < len) && (i != (A[i] - MIN))) {
if (A[A[i] - MIN] == A[i]) {
A[i] = A[len - 1];
A[len - 1] = Integer.MAX_VALUE;
len = len - 1;
} else {
int k = A[i] - MIN;
int temp = A[i];
A[i] = A[k];
A[k] = temp;
}
}
++i;
}
System.out.println("Final Array ... ");
printArr(A);
for (i = 1; i < len; i++) {
if ((A[i] - A[i - 1]) != 1) {
return false;
}
}
return true;
}

public static void printArr(int[] A) {
int len = A.length;
for (int i = 0; i < len; i++) {
System.out.print(A[i] + " ");
}
System.out.println();
}
}

Longest consecutive elements sequence

Given an int array which might contain duplicates, find the largest subset of it which form a sequence.

For example, in {5, 7, 3, 4, 9, 10, 1, 6, 15, 1, 3, 12, 2, 11} longest sequence is {1, 2, 3, 4, 5,6}.

The first thing that comes into our mind is to sort given array in O(n log n ) and look for longest consecutive elements sequence. Can we do it in Linear time?

The next solution would be using bit vector indexed by numbers from original array. It may not be justified due to incomparable solution space and original array size (although time complexity is O(n)).

Lets see how to solve this problem in O( n ) time complexity with constant space assuming the hashtable has O(1) time complexity and constant space complexity.

For each number A[i], put A[i] in hashMap<Int, List>
Also check if (A[i]+1) and (A[i]-1) exists in the Map,
If hashMap.contains((A[i]+1)) is true then append A[i] to the hashMap.get((A[i]+1));
If hashMap.contains((A[i]-1)) is true then append A[i] to the hashMap.get((A[i]-1));
And Append hashMap.get(A[i]+1) and hashMap.get(A[i]-1) to hashMap.get(A[i]);

In the end the iterate through all the keys of the hashMap and the largest List of hashMap.get(A[i]) is the longest sequence that exists in the input array.

 

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

public class LargestSequence {
public static void main(String[] args) {
int[] A = { 2, 3, 9, 10, 11, 4, 13, 5, 15, 6, 17, 7 };

HashSet<Integer> sequenceList = getLargestSequence(A);
Iterator<Integer> iter = sequenceList.iterator();
System.out
.println("Subset which forms the longest consecutive sequence: ");
while (iter.hasNext()) {
System.out.print(iter.next() + " ");
}
}

public static HashSet<Integer> getLargestSequence(int[] A) {
HashSet<Integer> result = new HashSet<Integer>();
if (A == null) {
return result;
}
int len = A.length;
Map<Integer, HashSet<Integer>> dataMap = new HashMap<Integer, HashSet<Integer>>();

for (int i = 0; i < len; i++) {
int less = A[i] - 1;
int more = A[i] + 1;
HashSet<Integer> list = new HashSet<Integer>();
boolean leftUpdated = false;
boolean rightUpdated = false;
if (dataMap.containsKey(less)) {
list = dataMap.get(less);
list.add(A[i]);
dataMap.put(less, list);

HashSet<Integer> keylist = dataMap.get(A[i]);
if (keylist != null) {
keylist.add(less);
keylist.addAll(list);
} else {
keylist = new HashSet<Integer>();
keylist.addAll(list);
}
dataMap.put(A[i], keylist);

leftUpdated = true;
}
if (dataMap.containsKey(more)) {
list = dataMap.get(more);
list.add(A[i]);
dataMap.put(more, list);

HashSet<Integer> keylist = dataMap.get(A[i]);
if (keylist != null) {
list.add(more);
// keylist.add(more);
keylist.addAll(list);
} else {
keylist = new HashSet<Integer>();
keylist.addAll(list);
}
dataMap.put(A[i], keylist);

rightUpdated = true;
}
if (!leftUpdated && !rightUpdated) {
list.add(A[i]);
dataMap.put(A[i], list);
}
}
Iterator<Entry<Integer, HashSet<Integer>>> it = dataMap.entrySet()
.iterator();
while (it.hasNext()) {
Map.Entry<Integer, HashSet<Integer>> pair = (Map.Entry<Integer, HashSet<Integer>>) it
.next();
if (pair.getValue().size() > result.size()) {
result = pair.getValue();
}
}

return result;

}
}

Conflicting appointments from a given list of n appointments

You are given 'n' appointments. Each appointment contains startime and endtime. You have to return all conflicting appointments efficiently starttime and endtime can range from a few min to few years.

Approach:

Suppose there are 5 events:

E1 => 13 : 15

E2 => 18 : 20

E3 => 11 : 24

E4 => 19 : 27

E5 =>  4  : 12

Now sort the events with start time:

E5: 4 : 12
E3: 11 : 24
E1: 13 : 15
E2: 18 : 20
E4: 19: 27
Now take the end time of first Event (E5) ie 12 and check in the start time the first event whose start time is greater than 12, in the above example E1 - with start time 13 is the event.
Now we can safely say that all the events less than E1 and greater than E5 are conflicting with E5 - which is E3 in our case.
With the same above logic, E3 is conflicting with E1, E2 and E4.
Time complexity = O(nlogn) for sorting the events on start time + O(nlogn) for searching a all the conflicting events for a given event Ei (1 <= i <= n).
So total time complexity: O(nlogn)

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;

public class ConflictingIntervals {

private static Event[] events = new Event[5];
private static Map<Integer, ArrayList<Integer>> eventConflicts = new HashMap<Integer, ArrayList<Integer>>();

public static void main(String[] args) {
initEvents();
findConflictingEvents();
}

public static void findConflictingEvents() {
Arrays.sort(events, new startEventComparator());
printEvents();
int len = events.length;

for (int i = 0; i < len; i++) {
int low = i + 1;
int high = len - 1;
int key = events[i].end;
int keyId = events[i].id;
int index = 0;
while (low <= high) {
int mid = (int) Math.floor((low + high) / 2);
if (key >= events[mid].start
&& ((mid + 1 < len) && (key <= events[mid + 1].start))) {
low = mid;
index = mid;
break;
} else if (key >= events[mid].start) {
low = mid + 1;
} else {
high = mid - 1;
}
}
ArrayList<Integer> evtList = eventConflicts.get(keyId);
low = low > high ? high : low;
for (int k = i + 1; k <= low && k < len; k++) {
if (k == i) {
continue;
}
evtList.add(events[k].id);

ArrayList<Integer> invList = eventConflicts.get(events[k].id);
invList.add(keyId);
eventConflicts.put(events[k].id, invList);
}
eventConflicts.put(keyId, evtList);
}

System.out.println("Conflicts are: ");

Iterator iterMap = eventConflicts.entrySet().iterator();

while (iterMap.hasNext()) {
Map.Entry<Integer, ArrayList> pair = (Map.Entry) iterMap.next();
System.out.print(pair.getKey() + " <> ");
Iterator iter = pair.getValue().iterator();
while (iter.hasNext()) {
System.out.print(iter.next() + " ");
}
System.out.println();
}
}

public static void printEvents() {
System.out.println("Events sorted with start time:");
int len = events.length;
for (int i = 0; i < len; i++) {
System.out.println(events[i].id + ": " + events[i].start + ":"
+ events[i].end);
}
}

public static void initEvents() {
Random rand = new Random();

int len = events.length;
int[] sArr = { 13, 18, 11, 19, 4 };
int[] eArr = { 15, 20, 24, 27, 12 };
int j = 0;
for (int i = 0; i < len; i++) {
int s = rand.nextInt(20) + 1;
int e = rand.nextInt(20) + 21;
events[i] = new Event(i + 1, sArr[j], eArr[j]);
eventConflicts.put(events[i].id, new ArrayList<Integer>());
++j;
}
}
}

class startEventComparator implements Comparator<Event> {
@Override
public int compare(Event o1, Event o2) {
if (o1.start < o2.start) {
return -1;
} else if (o1.start > o2.start) {
return 1;
} else {
return 0;
}
}
}

class Event {
int id;
int start;
int end;

public Event(int id, int s, int e) {
this.id = id;
this.start = s;
this.end = e;
}
}

Element which occurred at least M/2 times.

Given an array of n integers, where one element appears more than n/2 times. We need to find that element in linear time and constant extra space.

Don’t need to worry about the case when there are no elements with freq > m/2. There are multiple ways to solve the problem.

One approach is Find the median, it takes O(n) on an unsorted array(Kth smallest element approach). Since more than n/2 elements are equal to the same value, the median is equal to that value as well.

Another approach is Majority Counting Algorithm.


public class Majority {

public static int FindMostFrequentElement(int[] sequence)
{
int best = 0;
int count = 0;
for(int element:sequence)
{
if (count == 0)
{
best = element;
count = 1;
}
else
{
// Vote current choice up or down
count += (best == element) ? 1 : -1;
}
}
return best;
}
public static void main(String[] args) {
int [] A = {7,11,8,11,11,9,11,7,11,8,11,9,11};
System.out.println("Majority Element is"+FindMostFrequentElement(A));
}
}

Subsets such that the sum of numbers in the subset is a prime number.

Given a set of numbers [1-N] . Find the number of subsets such that the sum of numbers in the subset is a prime number.

Algorithm :

1) Generate all subsets using 0-1 Knapsack i.e this helps determine the number of ways it is possible get the value i, input ranging from 1 to n. The general complexity of 0-1 Knapsack is O(nK) where K is the sum of all elements in the vector. Since there are numbers ranging from 1 to n i.e sum is n(n-1)/2. The overall complexity becomes O(n^3)

For each number in the Sum S, check if there is subset of numbers from 1 to N that sum up to S - Yes that you can do with Subset Sum problem. Recurrence for the same is:
Sum[0,0]=True
For S=1 to L do Sum[0, S]= False
For k=1 to n do
     For S = 0 to L do
           Sum[k, S] = Sum[k-1, S] or Sum[k-1, S - x(k)]

2) Iterate all subsets which are prime. O(K)

public class PrimeSubset {

private static int[] primes;
private static int count = 0;

public static void main(String[] args) {
findPrimeSubsets(100);
}

public static void findPrimeSubsets(int N) {
int sum = (N * (N + 1)) / 2;
primes = new int[sum];
primes[0] = 2;
primes[1] = 3;
count = 2;

boolean[][] matrix = new boolean[N + 1][sum + 1];

for (int i = 0; i <= N; i++) {
matrix[i][0] = true;
}

for (int j = 1; j <= sum; j++) {
matrix[0][j] = false;
}

for (int i = 1; i <= N; i++) {
for (int j = 1; j <= sum; j++) {
matrix[i][j] = matrix[i - 1][j]
|| ((i <= j) && (matrix[i - 1][j - i]));
}
}

for (int i = 2; i <= sum; i++) {
if (matrix[N][i] && isPrime(i)) {
System.out.println(i);
primes[count] = i;
++count;
}
}
}

public static boolean isPrime(int n) {

if (n <= 1) {
return false;
} else if (n == 2 || n == 3) {
return true;
}
int sqrt = (int) Math.ceil(Math.sqrt(n));
boolean prime = true;
for (int k = 0; k < count && primes[k] <= sqrt; k++) {
if (n % primes[k] == 0) {
prime = false;
break;
}
}
return prime;
}
}

Thursday, April 4, 2013

Blocking Queue Implementation

public class MyBlockingQueue<T> {

private Queue<T> queue;
private AtomicInteger limit = new AtomicInteger(10);
private Lock put_lock = new ReentrantLock();
private Lock take_lock = new ReentrantLock();

public MyBlockingQueue(AtomicInteger limit){
queue = new LinkedList<T>();
this.limit = limit;
}

public boolean put(T item) throws InterruptedException{
put_lock.lockInterruptibly();
try{
while(queue.size() == limit.get()){
put_lock.newCondition().await();
}
put_lock.newCondition().signal();
queue.add(item);
}finally{
put_lock.unlock();
}

return true;
}

public T take() throws InterruptedException{
take_lock.lockInterruptibly();
try{
while(queue.size() == 0){
take_lock.newCondition().await();
}
take_lock.newCondition().signal();
return queue.poll();
}finally {
take_lock.unlock();
}
}
}