Amazon Interview Question
SDE-2sCountry: India
dynamic programming?
public static int findChain(int [] [] chain){
int [] dp=new int [chain.length];
dp [0] =1 ;
int max =1 ;
for (int i =1 ; i <chain.length ; ++i){
if (chain[i][0]>chain[i-1][1]){
dp [i]=dp[i]>dp[i-1]+1? dp [i] : dp[i-1]+1;
max=Math.max(dp[i], max);
}
}
return max;
}
@Scott your assumption is wrong about the array of pairs i.e. the your double array input is already sorted according to 2nd element. What of the array is not sorted. For example : {(50, 90), (5,24), (39,60), (15, 28), (27,40)}. Then you are selecting blindly the first pair as the start of the chain. So, O(n) solution of yours only works if the array is sorted.
isn't the problem is similar to O(nlgn) activity selection problem?
1) Sort the pairs according to their second element --> O(nlgn)
2) Select the first pair from the sorted array and print it. --> O(1)
3) Do following for remaining pairs in the sorted array. --> O(n)
---------------> If the first element of this pair is greater than the 2nd element of previously selected pair then select this pair and print it.
O(nlgn) solution:
public static int LongestChainPairs(Pair[] pairs)
{
Collection.sort(pairs); //Assume that Pair class implements comparable with the compareTo() method such that (a, b) < (c,d) iff b<c
int chainLength = 0;
//select the first pair of the sorted pairs array
pairs[0].print(); //assume print method prints the pair as “(a, b) ”
chainLength++;
int prev = 0;
for(int i=1;i<pairs.length; i++)
{
if(pairs[i].first >= pairs[prev].second)
{
pairs[i].print();
chainLength++;
prev = i;
}
}
return chainLength;
}
@zahidbuet106
why do we need to sort it based on second element only. We can do sorting based on first element also and follow rest of your approach. Whats wrong in that ??
@saurabh
Activity selection is a greedy algorithm which requires you to select a job each time according to the earliest finish time. In that sense you need to select the job with earliest finish time as the initial job, not the earliest started job. Also note that (start time, finish time) assumes start time < finish time . I mapped the pair problem as a activity selection problem by considering each pair as a job and first element as the starting time and 2nd element as finishing time because (a, b) exhibits a<b relation similar to start time<finish time in activity selection.I hope this answers your question.
Let's say input is a set of (x1,x2) points. Sort input by x2, then traverse the list and add elements to the chain which satisfy the required condition with regards to the tail of chain.
public static List<Pair> formChain(List<Pair> input) {
Collections.sort(input, new PairEndComparator());
LinkedList<Pair> chain = new LinkedList<>();
for (Pair p : input) {
if (chain.isEmpty() || chain.getLast().e < p.s)
chain.add(p);
}
return chain;
}
static class PairEndComparator implements Comparator<Pair> {
public int compare(Pair p1, Pair p2) {
return p1.e - p2.e;
}
}
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public class Chain {
class Segment implements Comparable<Segment> {
private final int start;
private final int end;
private final String name;
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
public String getName() {
return name;
}
Segment(int start, int end, String name) {
this.start = start;
this.end = end;
this.name = name;
}
@Override
public int compareTo(Segment s) {
if (this.end > s.end) {
return 1;
} else if (this.end == s.end){
return 0;
} else {
return -1;
}
}
}
private final Segment[] segments = {
new Segment( 8, 10, "A" ),
new Segment( 0, 7, "B" ),
new Segment( 11, 12, "C" ),
new Segment( 13, 16, "D" ),
new Segment( 0, 1, "E" ),
new Segment( 2, 15, "F" ),
new Segment( 4, 11, "G" ),
new Segment( 5, 6, "H")
};
public int findChainLength() {
List<Segment> tempSegments = new LinkedList<Segment>();
int result = 0;
for (Segment s : segments) {
tempSegments.add(s);
}
// O(nlogn) - sort segments by their end points:
Collections.sort(tempSegments);
Segment[] sortedSegments = (Segment[])tempSegments.toArray(new Segment[tempSegments.size()]);
int currentSegmentIndex;
currentSegmentIndex = 0;
System.out.print(sortedSegments[currentSegmentIndex].getName());
result++;
// O(n) worst case - scan and augment chain by adding the next
// shortest segment:
for (int index = 1; index < tempSegments.size(); index++) {
if (sortedSegments[index].getStart() > sortedSegments[currentSegmentIndex].getEnd()) {
currentSegmentIndex = index;
result++;
System.out.print(sortedSegments[currentSegmentIndex].getName());
}
}
return result;
}
public static void main(String[] args) {
Chain myChain = new Chain();
myChain.findChainLength();
return;
}
}
@us : Where are you using the method formChain() ? As per the question posted, we want to find only the length of the longest possible chain.
In such a case sorting the pairs denoted by P(s,e) in ascending order on P.e would give us the pair P which can act as a start of the segment (since we have found the pair P which would have the smallest P.s value in the entire chain.
Let Q be the queue where we store the parts of the segment.
Let INPUT be the list of sorted pairs.
Then do the following:
foreach Pair P in Input:
if(Q.isEmpty || Q.end.s < P.first)
Q.add(P)
return Q.length as the size of the longest segment
The important point to note here is that Q is composed of smaller segments that contribute to the largest segment, hence we effectively have all the possible segments that can be created from the provided input as well as the lengths of such segments.
1) Sort the sets on the basis of second number. Set (a,b) should be sorted on 'b'
2) Then, take the series satisfying second condition, that is, out of sets (a,b) & (c,d) b should be less than c.
For example,
(4,5) (7,9) (1,2) (11,15) (3,18)
After sorting it becomes:
(1,2)
(4,5)
(7,9)
(11,15)
(3,18)
It is being assured that in (a,b) a is always less than b.
Now, we can choose elements with respect to second condition as out of two sets, (a,b) & (c,d) b should be less than c.
this can be solved like the greedy approach of latest finish time job first.
in that we have to schedule the most no. of jobs which is here analogous to longest chain.
first we sort the pairs according to their second number. then we chose the first pair and then the next pair is next first pair in that sorted list such that its first number is. greater than second number of the previous chosen pair.
O(nlgn) using Activity Selection Problem:
1) Sort the pairs according to their second element --> O(nlgn)
2) Select the first pair from the sorted array and print it. --> O(1)
3) Do following for remaining pairs in the sorted array. --> O(n)
---------------> If the first element of this pair is greater than the 2nd element of previously selected pair then select this pair and print it.
- zahidbuet106 December 13, 2013