Goldman Sachs Interview Question
Software AnalystsCountry: United States
Interview Type: In-Person
Question: all the nodes together? all the nodes together in order? any 2 nodes together? any N nodes together?
If the question is: Do all the strings together in order form a palindrome?
Assign a to point to the first character of the first node.
Traverse to the end and assign this to the tail pointer.
Assign b to point to the last character of the tail node.
Check that the value of b == the value of a.
Move a 1 character towards the tail.
Move b 1 character towards the head.
When you run out of characters in a string, move to the next node in the direction you are going.
If b == a, and all values are the same, it is a palindrome.
Here only one change, this is DLL so first node have pointer of it's previous node which would be tail node so there will no need to traverse to end of the list to get last node. So now from first (head) node travel to next node of it and from tail travel to previous node of it, and when both head and tail node are same then stop.
Geet :- DLL means doubly linked list. What you are saying will be true for circular doubly linked list.
In DLL, previous pointer of first node points to null. While in circular DLL it points to tail.
So you have traverse all along the way to tail.
Go to last node,say y
x=head;
1.check whether x's string is palindrome with y's.
as there are N nodes in each of x,y...so if if those data is in array we can compare elements easily. If those nodes are also ll,then reverse y and then compare and finally reverse y to obtain original structure.
if not palindrome,return 0;
else goto step2
2.x=x->next;
if x==y
return 1;
y=y->prev;
if(x==y)
return 1;
go to step 1;
@Amit
What if the x and y's strings are of unequal length? The question is asking to check if the combined strings of all the nodes is a palindrome, which does not necessarily mean that the first and last strings will be of equal length and so will be the strings of second and the second-last nodes
public class DoublePalin {
public DoublePalin() {
super();
}
public static void main(String[] args) {
DoublePalin doublePalin = new DoublePalin();
DoublePalin.DoubleList<Character> list = doublePalin.new DoubleList<Character>();
String str = "aparnasharma";
for (int i = 0; i < str.length(); i++) {
list.insert(str.charAt(i));
}
System.out.println(list.palinCheck(str.length()));
}
class DoubleList<T extends Comparable> {
private DoubleList<T> next;
private DoubleList<T> prev;
private T data;
private DoubleList<T> head;
private DoubleList<T> tail;
public DoubleList() {
super();
}
public DoubleList(T data) {
this.setData(data);
}
public void insert(T data) {
DoubleList<T> item = new DoubleList<T>(data);
if (this.getHead() == null) {
this.setHead(item);
this.setTail(item);
} else {
this.getTail().setNext(item);
item.setPrev(this.getTail());
this.setTail(item);
}
}
public boolean palinCheck(int check) {
DoubleList<T> head = this.getHead();
if(head==null) return false;
DoubleList<T> tail = head.getNext()!=null?head.getNext().getNext():null;
while (tail != null)
{
head = head.getNext();
tail = tail.getNext()!=null?tail.getNext().getNext():tail.getNext();
}
if(check%2!=0) {tail =head.getNext(); head = head.getPrev();}
else {
tail = head.getNext();
}
while(head!=null) {
if(head.getData().compareTo(tail.getData())!=0) {
return false;
}
head = head.getPrev();
tail = tail.getNext();
}
return true;
}
public void traverse() {
DoubleList<T> head = this.getHead();
if (head == null)
return;
while (head != null) {
System.out.println(head.getData());
head = head.getNext();
}
}
public void retraverse() {
DoubleList<T> tail = this.getTail();
if(tail==null) return;
while(tail!=null) {
System.out.println(tail.getData());
tail = tail.getPrev();
}
}
public void setNext(DoubleList<T> next) {
this.next = next;
}
public DoubleList<T> getNext() {
return next;
}
public void setPrev(DoubleList<T> prev) {
this.prev = prev;
}
public DoubleList<T> getPrev() {
return prev;
}
public void setData(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setHead(DoubleList<T> head) {
this.head = head;
}
public DoubleList<T> getHead() {
return head;
}
public void setTail(DoubleList<T> tail) {
this.tail = tail;
}
public DoubleList<T> getTail() {
return tail;
}
public String toString() {
return this.getData()!=null?this.getData().toString():"";
}
}
}
palinCheck --> Logic
1). Move Head Pointer to middle of the list
2). Length is even then move tail to mid.getNext
3). Length is odd then move head to mid.getPrev and tail to mid.getNext
4). If there is any mismatch return false
1. Keep one pointer at start, another at end node
2. Compare first element of start with last element of end
3. If mismatch, return false
4. Otherwise, move start to next element, end to previous
5. If next/previous element does not exist, move to next/previous node and continue. Move them one by one and check exist condition
6. Exist condition, when both pointers are at same node same character
bool isPalindrome( Node *head )
{
if( head == NULL )
return true;
Node *start = head;
Node *end = head;
while( end->next != NULL )
end = end->next;
int i = 0, j = end->value.length() - 1;
while( ( start != end ) || ( i < j ) )
{
if( start->value.at( i ) != end->value.at( j ) )
return false;
i++;
if( i >= start->value.length() )
{
i = 0;
start = start->next;
if( ( start == end ) && ( i == j ) )
return true;
}
j--;
if( j < 0 )
{
end = end->previous;
j = end->value.length() - 1;
}
}
return true;
}
@DaCritique
Can you please be more specific, why it won't work? Or, give any input anomaly where it won't work.
0. Find the total node count and go to the middle of the DLL.
1. Reverse the DLL from its middle
2. Take two pointers - first at the first node and the second at the middle node.
3. Reverse the string of the node pointed by the second pointer and compare the strings. If they are equal or one is a substring of the other, go to next step, otherwise return false.
4. If both the strings are equal then advance both the first and second pointers else advance the pointer whose node's strings is smaller and check if either of the strings is equal or prefix of each other.
5. Repeat steps 3 and 4 until the second pointer gets past the end of the DLL and the first pointer gets to the middle node.
6 Return true.
@PseudoLife
Can you elaborate more on?
1. Reverse the DLL from its middle
How will you reverse, if middle is somewhere in between a string?
@Mukesh
You should not have skipped reading the first line.
>>0. Find the total node count and go to the middle of the DLL.
@Erasmus
Each node contains a string. Assume this list,
"abc" -> "defghi" -> "jk"
Now, how will your solution work?
@Mukesh
By reversing "ab"->"c"-> "cba" from the middle, I meant "ab"-> "cba"->"c". However, I realize that my procedure works only for a few particular cases and hence is not a generic solution. Further thoughts on it below.
The simplest solution, by using extra space, would be to concatenate all the individual strings of the DLL from left to right (or right to left) by writing their characters into a character array and then check if that character array is a palindrome.
Without using extra space, you need to traverse the DLL once to count the # of nodes to identify the middle node.(middle node position = total node count/2).
0. After that one can start from both ends of the DLL.
1. Compare the characters of the strings by traversing the string pointed by the first pointer in forward direction and the string by pointed by the second pointer in reverse direction.
2. If the first pointer exhausts the string, advance it to the "next" node.[Note: The second pointer can still be on its original node. It need not be moved simultaneously with the first one]
3. If the second pointer exhausts the string, advance it to the "previous" node.[First pointer can still be on its original node]
And a couple of base/boundary cases as below need to be handled.
4. After advancing, if the first pointer reaches the middle node, and if the second pointer had already reached the middle node, check that the rest of the string pointed to by second pointer is a palindrome or is empty.
5. A symmetric case of case 4.
Worked with the following cases and it seems my new solution works
a bcdc ba
abc c ba
a a
@Erasmus
Middle node may not always contain middle of string. Consider the list,
"abcdefghi"->"i"->"h"->"g"->"f"->"e"->"d"
@Mukesh
You are right yet again. If the notion of the 'middle' node is modified to be the one which contains the middle character of all the concatenated stings, the above algorithm should work . In the first pass, count the total number of characters of all the strings put together. In the subsequent passes, the forward and backward pointers can keep a track of the length of the strings they processed so far to infer whether or not the "middle" node is reached.
it's doubly linked list. We can traverse the list from both end. If we consider combined string of all nodes then finally it would be a single string.
- san August 16, 2013we can traverse DLL from both end and compare it character by character. if it matches throughout the operation then it would be palindrome else not.