Journal of a prolific coder
Thursday, December 1, 2011
Wednesday, August 18, 2010
Interview question: Find the intersection of two linked lists(corrupt)

I had this question for an in person tech screen and since I do not know the answer/idea before it was pretty difficult for me. So here's how my brainstorming went
- So the lists can be either like 5,4 or 4,4 or 4,5 nodes. So a simple approach of
- while(cur1!=cur2){
cur1=cur1.next;
cur2=cur2.next;
}
Would not work.
- The only distinguishing factor for the red node is that it has two links pointing to it.
- So if we can have a mechanism to identify the parent links of each node then we can find the red node
- Hence create a hash table with node and parent links
- But this approach would waste a lot of space and I know from gut feeling that this would not be an elegant solution.
- As expected my interviewer doesn't want this approach
- Hence create a hash table with node and parent links
- Have two pointers one fast and one slow and try to find if they merge
- For this my interviewer said this is not a cycle detection problem.
- I knew that and I was just trying to get a feeling if it could work
- For this my interviewer said this is not a cycle detection problem.
- Now I am desperate I mumbled something with bit vector and mapping each node to a bit vector
- Now he laughed sarcastically
- Now he laughed sarcastically
- I felt that this is not going my way at all but there is nothing at this stage than to try all the approaches that I come up with.
- How about finding the lengths and may be this could help
- As soon as I said this he asked me to write code for this.
- I was skeptical but as soon as I started writing code I realized the trick for this problem
- I was skeptical but as soon as I started writing code I realized the trick for this problem
- How about finding the lengths and may be this could help
- We have to make sure that both heads are at the same distance from the intersection point
- With this insight I got the solution – traverse both lists and find lengths- lenght1, lenght2.
- Whichever is larger move it length1-length2 times.
- Now use the first code snippet to find the intersection.
- With this insight I got the solution – traverse both lists and find lengths- lenght1, lenght2.
- After I wrote the code I said it was not clean and wanted to refactor because it has duplication and I didn't handle case where length1 is lesser than lenght2.
- He allowed me to do that and I got code in less than 10 lines! And two helper functions.
- He allowed me to do that and I got code in less than 10 lines! And two helper functions.
- After I written code we discussed test cases and where the code would fail, for example if there is no intersection or one list ends prematurely.
Urgh! Though I was able to solve this problem I felt very uncomfortable during the interview process, I mean I was being insulted or smirked at when I am trying to brainstorm a solution. Well whatever I got the answer. I only wished that I knew the solution before as many folks on career cup did if nothing but to save the embarrassment. So here goes the code.
public
ListNode findIntersection(ListNode h1,ListNode h2){
if(h1==h2)//this also handles both null case
return h1;
if(h1==null ||h2==null)
return
null;
ListNode cur1=h1;
ListNode cur2=h2;
int length1=findLength(cur1);
int length2=findLength(cur2);
if(length1>length2)
cur1=moveList(h1,length1-length2);
else
if(length2>length1)
cur2=moveList(h2,length2-length1);
while(cur1!=cur2){
cur1=cur1.next;
cur2=cur2.next;
}
return cur1;
}
private ListNode moveList(ListNode h1, int times) {
for(int i=0;i<times;i++){
h1=h1.next;
}
return h1;
}
private
int findLength(ListNode cur1) {
int count=0;
while(cur1!=null){
count++;
cur1=cur1.next;
}
return count;
}
Update: So even after my heroic solving of this problem, I got rejected. Well I don't know what to say.
Also there are 6 approaches to solve this - http://exclusiveminds.com/2010/03/05/write-a-function-to-get-the-intersection-point-of-two-linked-lists/
Friday, August 13, 2010
How do edit column wise in an editor
Wednesday, August 11, 2010
Interview question: Convert a sorted doubly linked list to Binary Search Tree.
This question has special meaning for me because I was asked this question back in April 2009 by Windows Azure team and I was not able to create a working code then. As a result I didn't get an offer. Today I thought of cracking this code and worked in for a few hours and successfully got a working running solution! I tried to search for a curt answer to this question but could not find exact code but only the idea. Idea is simple
Get to the middle of linked list and make it the root of the tree, then do the same for the left and right half's of the linked list iteratively.
The code that I jotted down in the first 5 minutes is exactly all that needed for this to work. Though during my walk through I convinced myself that it wouldn't work and needed extra logic for checking if a node already exists in tree.
BinarySearchTreeNode createBST(DoubleLinkedList dll, int start, int end) {
BinarySearchTreeNode root=null;
if(start<=end){
int mid=(start+end)/2;
DoubleLinkedListNode cur=dll.getNode(mid);
root=new BinarySearchTreeNode(cur.item);
root.leftChild=createBST(dll, start, mid-1);
root.rightChild=createBST(dll,mid+1,end);
}
return root;
}
The second version I had with extra logic.
BinarySearchTreeNode createBST(DoubleLinkedList dll, int start, int end) {
BinarySearchTreeNode root=null;
if(start<=end){
int mid=(start+end)/2;
DoubleLinkedListNode cur=dll.getNode(mid);
if(cur.visited)
return root;
else
root= new BinarySearchTreeNode(cur.item);
cur.visited=true;
root.leftChild=createBST(dll, start, mid-1);
root.rightChild=createBST(dll,mid+1,end);
}
return root;
}
Recursion works in mysterious ways. I am still not entirely clear why we don't the extra logic but we don't J . Recursion is really mysterious!
For this code actually work there is lot of boiler plate that's needed, which I give below. In it one I liked is overriding the toString() method so that eclipse debugger is able to show the string and System.out.println(node) works.
package com.code.prolificcoder;
//To covert a sorted doubly linked list to binary search tree
class DoubleLinkedListNode{
int
item;
DoubleLinkedListNode next;
DoubleLinkedListNode prev;
public DoubleLinkedListNode(int item) {
this.item=item;
next=null;
prev=null;
}
@Override
public String toString(){
StringBuilder sb=new StringBuilder();
if(this.prev==null)
sb.append("X--");
else
sb.append(this.prev.item+"--");
sb.append(this.item);
if(this.next==null)
sb.append("--X");
else
sb.append("--"+this.next.item);
return sb.toString();
}
}
class DoubleLinkedList{
int
size;
DoubleLinkedListNode head;
public DoubleLinkedListNode getNode(int num){
if(num<0)
return
null;
DoubleLinkedListNode cur=head;
int i=0;
while(cur!=null){
if(i==num)
return cur;
i++;
cur=cur.next;
}
return cur;
}
}
class BinarySearchTreeNode{
int
item;
BinarySearchTreeNode leftChild;
BinarySearchTreeNode rightChild;
public BinarySearchTreeNode(int item) {
this.item=item;
leftChild=null;
rightChild=null;
}
public BinarySearchTreeNode(){}
@Override
public String toString(){
StringBuilder sb=new StringBuilder();
if(this.leftChild==null)
sb.append("X--");
else
sb.append(this.leftChild.item+"--");
sb.append(this.item);
if(this.rightChild==null)
sb.append("--X");
else
sb.append("--"+this.rightChild.item);
return sb.toString();
}
}
public
class DLLtoBST {
public
static
void main(String args[]){
DoubleLinkedListNode d4=new DoubleLinkedListNode(13);
DoubleLinkedListNode d3=new DoubleLinkedListNode(11);
DoubleLinkedListNode d2=new DoubleLinkedListNode(9);
DoubleLinkedListNode d1=new DoubleLinkedListNode(7);
DoubleLinkedListNode d0=new DoubleLinkedListNode(3);
d0.next=d1;d0.prev=null;
d1.prev=d0;d1.next=d2;
d2.prev=d1;d2.next=d3;
d3.prev=d2;d3.next=d4;
d4.prev=d3;d4.next=null;
DoubleLinkedList dll=new DoubleLinkedList();
dll.head=d0;
DLLtoBST db=new DLLtoBST();
BinarySearchTreeNode root =db.createBST(dll,0,4);
System.out.println(root);
System.out.println(root.leftChild);
System.out.println(root.leftChild.rightChild);
System.out.println(root.rightChild);
System.out.println(root.rightChild.rightChild);
}
private BinarySearchTreeNode createBST(DoubleLinkedList dll, int start, int end) {
BinarySearchTreeNode root=null;
if(start<=end){
int mid=(start+end)/2;
DoubleLinkedListNode cur=dll.getNode(mid);
root=new BinarySearchTreeNode(cur.item);
root.leftChild=createBST(dll, start, mid-1);
root.rightChild=createBST(dll,mid+1,end);
}
return root;
}
}
Monday, August 9, 2010
Interview question: Find if word exists in a crossword
In my preparation for google interview, I thought I should go over some problem in career cup and I found this crossword problem pretty interesting. In my mock interview yesterday I later found a simpler solution using an intuitive recursion, so I thought I should try this problem.
The problem statement is:
Given a puzzle of letters/ characters e.g.
a e r o p s
b h a r l s
w r i s l o
a s n k t q
Write a function to which this puzzle and a word will be passed to test whether that word exists in the puzzle or not.
e.g. rain and slow will return true. rain is present in the second column and slow in the third row wrapped around.
This problem reminded me of maze exploration which can be done recursively and I started coding in that mode.
- First I would have a main recursive function which checks if the first word matches
private boolean stringFinder(char[][] ar, String str) {
int size=ar.length;
if(str.length()>size+1) return false;
int k=0;
char[] charArray=str.toCharArray();
for(int i=0;i<size;i++)
for(int j=0;j<size;j++)
if(ar[i][j]==charArray[k])
- If matches recursively check all the four directions
return isMatch(ar,charArray,i,((j+1)%size),k+1)||
isMatch(ar,charArray,((i+1)%size),j,k+1)||
isMatch(ar,charArray,((i-1)%size),j,k+1)||
isMatch(ar,charArray,i,((j-1)%size),k+1);
- In each of the directions again search for a match. (this is wrong)
private boolean isMatch(char[][] ar, char[] charArray, int i, int j, int k, Direction dir) {
int size=ar.length;
if(k==charArray.length-1)
{
if(ar[i][j]==charArray[k]) return true;
else return false;
}
if(ar[i][j]==charArray[k])
return isMatch(ar,charArray,i,((j+1)%size),k+1)||
isMatch(ar,charArray,((i+1)%size),j,k+1)||
isMatch(ar,charArray,((i-1)%size),j,k+1)||
isMatch(ar,charArray,i,((j-1)%size),k+1);
}
return false;
}
I verified this approach and it was working with pen and paper. So I opened up eclipse with a jolly mood and though I am a genius.
But there were several mistakes
- When the inevitable happened- the program is not responding as expected, I found that I am searching in all direction after I found a direction. So I modified my approach to include a direction enum.
- And tried to change i and j values based only on the direction. This time I got the directions wrong and it took a while to overcome it.
- Then I got the problem of comparing next recursion when I wanted to be in the current one. So I changed the order.
- Finally I got the result when I send in "rain" and the output is true ! And then I again checked for "slow" and magic it returned true!!
- But when I am sending in a string that does not exist I am getting an exception. Reason: I am sending in negative indexes.. Even though I am wrapping i and j values I forgot to take of –ve signs.
So finally my code became like this
package com.code.prolificcoder;
public class StringFinder {
enum Direction{up,down,left,right};
public static void main(String args[]){
char[][] ar=new char[][]{{'m','s','s','h'},
{'a','t','c','i'},
{'p','d','a','n'},
{'s','a','t','h'},
};
String str="tcia";
StringFinder sf=new StringFinder();
System.out.print(sf.stringFinder(ar,str));
}
private boolean stringFinder(char[][] ar, String str) {
int size=ar.length;
if(str.length()>size+1) return false;
int k=0;
char[] charArray=str.toCharArray();
for(int i=0;i<size;i++)
for(int j=0;j<size;j++)
if(ar[i][j]==charArray[k])
return isMatch(ar,charArray,i,Math.abs((j+1)%size),k+1,Direction.right)||
isMatch(ar,charArray,Math.abs((i+1)%size),j,k+1,Direction.down)||
isMatch(ar,charArray,Math.abs((i-1)%size),j,k+1,Direction.up)||
isMatch(ar,charArray,i,Math.abs((j-1)%size),k+1,Direction.left);
return false;
}
private boolean isMatch(char[][] ar, char[] charArray, int i, int j, int k, Direction dir) {
int size=ar.length;
if(k==charArray.length-1)
{
if(ar[i][j]==charArray[k]) return true;
else return false;
}
if(ar[i][j]==charArray[k]){
if(dir==Direction.down)
i=Math.abs((i+1)%size);
else if(dir==Direction.right)
j=Math.abs((j+1)%size);
else if(dir==Direction.left)
j=Math.abs((j-1)%size);
else //dir==Direction.up
i=Math.abs((i-1)%size);
return isMatch(ar,charArray,i,j,k+1,dir);
}
return false;
}
}
It took me more than 2 hours to get this version, in an interview you are not given this many chances and a compiler and a debugger. I should be able to correct my bugs in walkthroughs, all in all scary.
Update: My tester wife found another bug in this code. Whenever there is a search for a char that is present twice I am returning the result of the first one which could be false but the later could be true.
For eg: "scat" in the above it will return false because the first match for s resulted in false and I returned it. To solve this I update the code as follows.
private
boolean stringFinder(char[][] ar, String str) {
int size=ar.length;
if(str.length()>size+1) return
false;
int k=0;
boolean found=false;
char[] charArray=str.toCharArray();
for(int i=0;i<size;i++)
for(int j=0;j<size;j++)
if(ar[i][j]==charArray[k])
found= isMatch(ar,charArray,i,Math.abs((j+1)%size),k+1,Direction.right)||
isMatch(ar,charArray,Math.abs((i+1)%size),j,k+1,Direction.down)||
isMatch(ar,charArray,Math.abs((i-1)%size),j,k+1,Direction.up)||
isMatch(ar,charArray,i,Math.abs((j-1)%size),k+1,Direction.left)||found;
return found;
}
Wednesday, August 4, 2010
How not to do a technical phone interview
- Got the technical question completely wrong. The question is "How would you reverse a string without using a for loop". To be honest I was expecting a simpler question this question kind of got be off guard. So, I asked if I can use a while loop, he goes to say that I can't use a iterator. Then I got this idea of swapping start and end pointers until start <= end and he did not object to it. But on later thoughts I think he gave up on me, what he is actually looking for a recursion based solution. Its not simple or intuitive but a recursive solution can be made.
- What is the difference between abstract class and interface, I have been asked this question probably 5 times in an interview now and I can't explain why I stumbled today. I was talking about implementing an abstract class etc.. while the main difference is in how many of them a class can use. A class can have multiple interfaces but can only have one parent class. Though I knew it I didn't say it.
- I didn't get the company website before the interview, I actually didn't understand so I couldn't look at it.
- I didn't take time when I have to a)while solving the problem b)while constructing sentences. I really don't understand my rush during the phone interview.
- I am not getting the attitude of its ok to pause before attempting to say something. It creates a bad impression to mumble something than to pause a while and say something more coherent.
Tuesday, August 3, 2010
Get a landline at your computer with google voice + skypein + regular phone
Attempt #5
- Download Skype.
- Buy an online number from Skype
- Add a phone in google voice using this number
- Install google voice plugin for chrome (optional)
- Make calls from your desk by clicking on the phone number and selecting SkypeIN
- Talk from your computer
- Receive calls on your computer through skype.