Linkedin Interview Question
Software Engineer / DevelopersInterview Type: Written Test
So here you're traversing twice, aren't you? Once for each of the two pointers you have.
Use One pointer to the list and a queue of size 5:
1) traverse to the 5th node
2) insert the element at the queue
3) if the queue is full, take rear element out and insert the new element at the front
4) repeat it till the pointer reaches null
5) the rear pointer of the queue contains the 5th element from the tail of the list..
Cobra,
when we require 5th element from end. so we can use variable also.. then what is the need of queue ?
if you use a variable, how will you say it is a nth element from tail??
are u going to use n variables to find nth element from tail?
Good argument, cobra. It's always good to design your code to be easy to change. With your approach the value 5 would probably be one parameter passed to the queue in one place in the code.
One small correction: you need to be inserting elements into the queue even as you traverse to the 5th node.
This question talks about LinkedList, not a queue
You have to tell the fifth element from last using a linkedList
Here is the java implementation, hope it helps.
public static Node get5thFromTail(Node head){
Queue<Node> queue = new LinkedList<Node>();
while(head != null){
if(queue.size() == 5){
queue.poll();
queue.offer(head);
} else {
queue.offer(head);
}
head = head.next;
}
//There are less than 5 node
if(queue.size() < 5){
return null;
}
return queue.poll();
}
1) Take two pointers both at the start of linklist.
2) Advance one pointer by 5 positions.
3) then advance both the pointers simultaneously until second pointer becomes null.
4) Return first pointer.
node* fun(node* head)
{
if(head==null)
{cout<<"not enough elements"; return null;}
node*ptr1,*ptr2=head;
for (int i=0;i<5&&ptr2!=null;i++)
ptr2=ptr2->next;
if(ptr2==null) {cout<<not enough elements; return null;}
while (ptr2!=null)
{
ptr1=ptr1->next;
ptr2=ptr2->next;
}
return ptr1;
}
Example: A->B->C->D->E->F->G->*(end)
5th from last: C
after loop1
ptr2=F
after loop2
ptr1=c
a single pass means , a node can be visited only once.. whether it is single pointer or two pointer..
you are done two pass... first pointer traverse n elements and the second pointer traverse n-5 elements
Cobra is right - you have done more than one pass here. Also you have not accounted for the fact that if you don't have enough elements you will return the head, which is not correct either since it is actually not the 5th element from the list. NULL would be a more proper return in that case.
Cobra,
Single pass or two pass is said in terms of time taken to do the task. If you are traversing the whole list once and again traverse to find 5th element from tail that is 2 pass. If you use 2 variables, you can traverse the list in 1 pass's time only so this method of using 2 variable is considered as one pass and not two pass.
I hope I made myself clear.
We can do this in one pass using a pointer and a queue of length 5
pseudo code
function 5th_from_tail( head )
s = queue length 5
s = Null
ptr = head
while ptr != Null
s.push_to_head(ptr)
ptr = ptr -> next
element = s.pop_from_tail()
if element == Null
return "not enough elements"
else
return element
we can do this without using a queue. we need to have only two pointer. So, space complexity will be less
But as mentioned in the question, space complexity is not the issue. but list should be transversed only once. And using two pointer that can't be done.
list_node * get5thNode()
{
list_node * temp = NULL;
list_node * runner = headNode;
int index = 1;
while(runner->next != NULL)
{
runner = runner->next;
if(index > 5)
{
if(!temp)
temp = headNode;
else
temp = temp->next;
}
index++;
}
return temp;
}
O(n) solution
General Solution to find nth node from tail
public class FifthNodeFromTailLinkedList {
private static final int nthNode = 5;
public static Node getNthNodeFromTail(Node head) {
if (head == null) {
return null;
}
Node nthTailNode = null;
int count = 0;
Node node = head;
while (node != null) {
count ++;
if (count == nthNode) {
nthTailNode = head;
break;
}
node = node.getNext();
}
while (node.getNext() != null) {
nthTailNode = nthTailNode.getNext();
node = node.getNext();
}
return nthTailNode;
}
public static void main(String args[]) {
Node node = new Node(1);
node.setNext(new Node(2));
node.getNext().setNext(new Node(3));
node.getNext().getNext().setNext(new Node(4));
node.getNext().getNext().getNext().setNext(new Node(5));
node.getNext().getNext().getNext().getNext().setNext(new Node(6));
System.out.println(getNthNodeFromTail(node).getValue());
}
}
class Node {
private int value;
private Node next;
public Node(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
Output:
2
/*
* Write a function that would return the 5th element from the
* tail (or end) of a singly linked list of integers, in one pass,
* and then provide a set of test cases against that function
* (please do not use any list manipulation functions that you
* do not implement yourself).
*/
class App {
public static void main(String[] args) {
int arr[] = new int[] { 0, 1, 2, 3, 4, 5, 6 };
int lastLocation = 0;
while (true) {
try {
System.out.println(arr[lastLocation]);
lastLocation = lastLocation + 5;
} catch (ArrayIndexOutOfBoundsException e) {
//System.out.println("arr Out of index: " + lastLocation);
break;
}
}
lastLocation--;
for (int i = 0; i < 5; i++) {
try {
// This sysout statement ensure that same element is not hit
// twice
System.out.println(arr[lastLocation]);
if(lastLocation < 4) {
System.out.println("Array Length less than 5");
break;
}
// System.out.println("Last element of array: "
// + arr[lastLocation]);
System.out.println("5th Last element of array: "
+ arr[lastLocation - 4]);
break;
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(lastLocation--);
}
}
}
}
two pointer and one counter
1) one pointer keep moving till the end, everyone move, counter will increase one
2) when counter is >= Nth (e.g 5), the second pointer will starting pointing from head, since then, every since first pointer move, second pointer will also move
3) when first move till the end of list, return second pointer
using System;
namespace ConsoleApplication1
{
class NTHElementFromTailFromList
{
static void Main(string[] args)
{
Node node = new Node
{
value = "1",
next = new Node
{
value = "2",
next = new Node
{
value = "3",
next = new Node
{
value = "4",
next = new Node
{
value = "5",
next = new Node
{
value = "6",
next = new Node
{
value = "7",
next = null
}
}
}
}
}
}
};
Node nTh = FindNthElementTail(node, 2);
Console.WriteLine(nTh);
}
static Node FindNthElementTail(Node n, int nth)
{
Node nThElement = null;
Node head = n;
int count = 0;
while (n != null)
{
count++;
if (count >= nth)
{
if (nThElement == null)
{
nThElement = head;
}
else
{
nThElement = nThElement.next;
}
}
n = n.next;
}
return nThElement;
}
}
class Node
{
public Node next { get; set; }
public string value { get; set; }
public override string ToString()
{
return this.value;
}
}
}
// maintain two pointers fast and slow
ListNode* kthNodeFromEnd(ListNode* head, int k)
{
if (head == NULL) return NULL;
ListNode* fast = head, slow = head;
while (--k && fast->next != NULL) fast = fast->next;
if (fast == NULL) return NULL;
while (fast->next != NULL) {
fast = fast->next;
slow = slow->next;
}
return slow;
}
{ public static void findpos(LinkedList linkedList,LinkedList.Node head,int n)
{
LinkedList.Node temp = head;
LinkedList.Node pos = head;
int length=0;
int i=0;
while (i<n){
temp=temp.next();
i++;
}
while(temp.next() !=null)
{
pos=pos.next();
temp=temp.next();
}
System.out.println("Element at n th from last = "+ n + " of LinkedList : " + pos.data());
}
public class NthFromLast {
static class Node {
int value;
Node next;
public Node(int value, Node next) {
this.value = value;
this.next = next;
}
public String toString() {
return String.valueOf(value);
}
}
int counter = 0;
Node nthNode;
public Node getNthNode(Node first, int n) {
getNthNodeRecursive(first, n);
return nthNode;
}
private void getNthNodeRecursive(Node first, int n) {
if(first == null) {
return;
}
if(first.next != null) {
getNthNodeRecursive(first.next, n);
}
counter++;
if(counter == n) {
nthNode = first;
}
}
public static void main(String [] args) {
Node first = new Node(1,
new Node(2, new Node(3, new Node(4, new Node(5, new Node(6, null))))));
NthFromLast n = new NthFromLast();
System.out.println(n.getNthNode(first, 4));
}
}
This one is using recursion, single pass and O(1) space. Apologies for the duplicate post.
public class NthFromLast {
static class Node {
int value;
Node next;
public Node(int value, Node next) {
this.value = value;
this.next = next;
}
public String toString() {
return String.valueOf(value);
}
}
int counter = 0;
Node nthNode;
public Node getNthNode(Node first, int n) {
getNthNodeRecursive(first, n);
return nthNode;
}
private void getNthNodeRecursive(Node first, int n) {
if(first == null) {
return;
}
if(first.next != null) {
getNthNodeRecursive(first.next, n);
}
counter++;
if(counter == n) {
nthNode = first;
}
}
public static void main(String [] args) {
Node first = new Node(1,
new Node(2, new Node(3, new Node(4, new Node(5, new Node(6, null))))));
NthFromLast n = new NthFromLast();
System.out.println(n.getNthNode(first, 4));
}
}
whats wrong with using something like
current=first
while(current.next.next.next.next.next!=null)
current=current.next;
where next is the next node.
errr!!! i think it confusing. I am using current.next.next.next.next.next only as a checking condition
i am incrementing current as current.next.
correct me if i am wrong
class Node {
Object data;
Node next;
};
Node 5thToTail(Node head)
{
if (head == null)
{
throw Exception("Error: empty linked list");
}
else
{
Node p1 = head, p2 = head;
int i = 1;
for(; i<5; i++)
{
if (p1.next != null)
{
p1 = p1.next;
}
}
if (i < 5)
{
throw Exception("Error: elements are less than 5 in the linked list");
}
while (p1.next != null)
{
p1 = p1.next;
p2 = p2.next;
}
return p2;
}
}
1)Take 2 pointer move one pointer by 5 position ie, the difference between the two pointer is 5.
- Anand August 08, 20122)Now traverse through the list till the first pointer reaches the end of the list
3) now the second pointer will be pointing to the 5th element from the last.