Google Interview Question
Software Engineer / DevelopersCountry: United States
Interview Type: Phone Interview
@will_in_seattle : Do we need to care about duplicates ?
I guess not. Because while taking intersection or union, the result is a set. As set does not contains duplicates, so there is no need to check for duplicates.
Comments pls
If we were talking about sets with respect to their mathematical definition or the way that Java defines them, then I would say that discarding them is alright. However, since we are talking about data and the question doesn't specify to discard any data, then we should assume that the data is relevant and not discard it.
Yes, you are correct. Even question sounds incomplete and can be interpreted in two ways, where other is finding the merging(intersection) point in two list, as the algo given by Anonymous.
This question is ambiguous and better to have discussion with interviewer to clarify a bit. May be interviewer deliberately did not revealed much details hoping that candidate will ask them, just to see his/her problem solving skills.
:-)
@Will
Do you really need this test,
if(i < s2.size()) {
if(hashTable.get(s2.get(i))!= 0) {
hashTable.put(s2Val, value - 1);
intersection.add(s2Val);
}
}
It is covered by for loop.
Or I missed something ?
Thanks
@Will,
What about if there are negative numbers in the unsorted lists?
The program will then need to cater to that condition as well.
If we can discard printing duplicates as it'll violate the set definition itself here is what I think might work.
Dont increment hash values. Just let them be 1 for +ve numbers for one of the lists. If the same number is found in the other list simply set it to 0.
For -ve numbers hash on the absolute value. But in the hash table set that value as 2 (or something other than 1 and 0).
So if a list had +23 and the other -23, though they'll hash to the same bucket (index) but we'll still be able to determine if we are comparing two different numbers.
Just sharing my thoughts. I might be wrong!
Thanks
My program doesn't handle negative numbers? I haven't tried it out, but why wouldn't it? Also, where is the word "set" in the question? Intersection of data does not imply set.
@Will,
"My program doesn't handle negative numbers?" ---
Sorry I didn't follow. Are you asking me or telling me?
I was just putting across a solution which "might" cater to the case where the lists have negative numbers also.
Also, the word set is not mentioned explicitly but "intersection" sort of hints towards the same. I agree though that it is open to interpretation.
Anyways I was trying to discuss not argue!
first, I think you should sort these two list in max(O(nlogn), O(mlogm)) time, then traverse two lists to check their common data and store them in a new array or list in O(m+n) time. so the time complexity is max(O(nlogn), O(mlogm)). later I will give my codes.
@yingsun1228 : Why you need sorting ?
1) Make a hashmap/hashset with one list.
2) Now traverse second list and check if hashmap/hashset contains that element. If it contains then print it, otherwise move on.
" traverse two lists to check their common data and store them in a new array"
How will you traverse then, traversing will take O(n^2) here in your case. As you have to compare each element of list 1 to each element of list2
traverse the first list and get the lenght. Traverse the 2nd and get the length.
Get the difference len1- len2. On the longest list travel len1-len2 distance from start. Now start tarversing both the lists node by node. you will find the intersection.
The question is not clear itself. First I also thought of same thing.
But the question can be to find intersection of elements.
For. ex. -
List 1 - {14,56,2,78,90}
List 2 - {15,10,56,36,2, 80,65}
We have to return 56 and 2
---------------------
I don't think here we need to find merging point of two list.
If it is so, then your solution is correct.
void intersection(vector<int> list1, vector<int> list2) {
map<int, int> hashTable;
map<int, int>::iterator it;
for (int i=0; i<list1.size(); i++) {
it = hashTable.find(list1[i]);
if (it == hashTable.end()) hashTable.insert(pair<int, int>(list1[i], 1));
else it->second++;
}
for (int i=0; i<list2.size(); i++) {
it = hashTable.find(list2[i]);
if (it != hashTable.end() && it->second != 0) {
it->second--;
std::cout<<list2[i]<<endl;
}
}
}
Node getIntersection(Node first, Node second) {
HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
Node result = first;
Node cur = null;
while (first != null) {
cur = first;
int num = first.data;
if (hm.contains(num))
hm.put(num, hm.get(num)+1);
else
hm.put(num, 1);
first = first.next;
}
while(second != null) {
int num = second.data;
if (hm.contains(num)) {
hm.put(num, hm.get(num)-1);
}
else {
hm.put(num, -1);
}
if (hm.get(num) < 0) {
cur.next = second;
cur = second;
}
second = second.next;
}
return result;
}
nitingupta180's answer is close, but doesn't handle the scenario where there are duplicates. This answer is O(n) time complexity. The additional step required is to decrement the values in the hash table until they hit zero while checking the elements for existence (from the second array).
Here is the source for the complete answer as well as a test scenario:
- Will_In_Seattle January 22, 2013