How to find middle element of LinkedList in Java in one pass

How do you find middle element of LinkedList in one pass is a programming question often asked to Java and non Java programmers in telephonic Interview. This question is similar to  checking palindrome or  calculating factorial, where Interviewer some time also ask to write code. In order to answer this question candidate must be familiar with LinkedList data structure i.e. In case of singly LinkedList, each node of Linked List contains data and pointer, which is address of next Linked List and last element of Singly Linked List points towards null. Since in order to find middle element of Linked List you need to find length of LinkedList, which is counting elements till end i.e. until you find the last element on Linked List. What makes this data structure Interview question interesting is that you need to  find middle element of LinkedList in one pass and you don’t know length of LinkedList. This is where candidates logical ability puts into test, whether he is familiar with space and time trade off or not etc. As if you think carefully you can solve this problem by using two pointers as mentioned in my last post on  How to find length of Singly Linked List in Java. By using two pointers, incrementing one at each iteration and other at every second iteration. When first pointer will point at end of Linked List, second pointer will be pointing at middle node of Linked List.  In fact this two pointer approach can solve multiple similar problems e.g. How to find 3 rd element from last in a Linked List in one Iteration or How to find nth element from last in a Linked List. In this Java programming tutorial we will see a Java program which finds middle element of Linked List in one Iteration.


Java program to find middle element of LinkedList in one pass

How to find middle element of Linked List in Java with ExampleHere is complete Java program to find middle node of Linked List in Java. Remember LinkedList class here is our custom class and don’t confuse this class with  java.util.LinkedList  which is a popular Collection class in Java. In this Java program, our class LinkedList represent a linked list data structure which contains collection of node and has head and tail. Each Node contains data and address part. Main method of LinkedListTest class is used to simulate the problem, where we created Linked List and added few elements on it and then iterate over them to find middle element of Linked List in one pass in Java.

import  test.LinkedList.Node ;

/**
 * Java program to find middle element of linked list in one pass.
 * In order to find middle element of linked list we need to find length first
 * but since we can only traverse linked list one time, we will use two pointers
 * one which we will increment on each iteration while other which will be
 * incremented every second iteration. so when first pointer will point to the
 * end of linked list, second will be pointing to the middle element of linked list
 * @author
 */

public class LinkedListTest  {
  
  
     public static void main ( String args [])  {
         //creating LinkedList with 5 elements including head
       LinkedList linkedList =  new LinkedList () ;
       LinkedList. Node head = linkedList. head () ;
      linkedList. add (  new LinkedList. Node ( "1" )) ;
      linkedList. add (  new LinkedList. Node ( "2" )) ;
      linkedList. add (  new LinkedList. Node ( "3" )) ;
      linkedList. add (  new LinkedList. Node ( "4" )) ;
    
       //finding middle element of LinkedList in single pass
       LinkedList. Node current = head ;
       int length =  0 ;
       LinkedList. Node middle = head ;
    
      while (current. next ()  !null ){
          length++ ;
          if (length %2 == 0 ){
              middle = middle. next();
           }
          current = current. next () ;
       }
    
      if(length%2 == 1) {
          middle = middle. next();
       }

       System. out. println ( "length of LinkedList: " + length ) ;
       System. out. println ( "middle element of LinkedList : " + middle ) ;
      
     } 
  
}

class LinkedList {
     private Node head ;
     private Node tail ;
  
     public LinkedList (){
         this. head =  new Node ( "head" ) ;
        tail = head ;
     }
  
     public Node head (){
         return head ;
     }
  
     public void add ( Node node ){
        tail. next = node ;
        tail = node ;
     }
  
     public static class Node {
         private Node next ;
         private String data ;

         public Node ( String data ){
             this. data = data ;
         }
      
         public String data ()  {
             return data ;
         }

         public void setData ( String data )  {
             this. data = data ;
         }

         public Node next ()  {
             return next ;
         }

         public void setNext ( Node next )  {
             this. next = next ;
         }
      
         public String toString (){
             return this. data ;
         }
     }
}

Output:
length of LinkedList: 4
middle element of LinkedList : 2


That’s all on  How to find middle element of LinkedList in one pass. As I said this is a good interview question to separate programmers from non programmers. Also technique mentioned here to find middle node of LinkedList can be used to find 3rd element from Last  or nth element from last in a LinkedList as well.

Other  Java programming tutorials from Javarevisited blog
20 comments :
Pio Jac said...

Maybe my mind is still not awaken after Christmas laziness, but... does this code really return middle element? I think it returns last element with even index. In this code it is solved like you were incrementing index every second time. If you update reference to current every second time, nothing good will come out of this. I'd set middle = middle.next() in loop and also ... initialize length as 0 (I don't consider head element as real element of the list (length should return number of elements carrying data). Greetings!

December 28, 2012 at 2:55 AM
Javin Paul said...

@Pio Jac, you are right if we don't consider head as real element. In that case initialing length with 0 make sense. Also In order to handle odd length e.g. 3, 5 or 7 where middle element is not updated, we need to handle once loop finished. I have updated code. Thanks for pointing out, it seems, its me, who has Christmas laziness :)

December 28, 2012 at 4:23 AM
Anonymous said...

Can you please write code for How to find 3rd element from last in Singular Linked List, I didn't get your point on saying that same technique can be used to find Nth element from last in singly linked list. Sorry.

January 3, 2013 at 12:57 AM
Liu Jin said...

I was asked to find middle item in a linked list in single pass and when I asked what is length of linked list they say, you need to find that as well. I didn't thought that I can use two pointers or two variables to keep track of middle and last item, something I missed. By the way What is big O for best case and worst case for this solution ?

January 3, 2013 at 6:58 PM
Anonymous said...

In what aspect does this separate the programmers from nonprogrammers, even when you yourself didn't elaborate a complete algorithm?
What is a programmer and what is a nonprogrammer?

January 3, 2013 at 11:10 PM
Javin @ JDBC Best practices said...

@Anonymous, aspect here is coding, converting logic to code. algorithm here is simple where one pointer is incremented on each iteration, while other is incremented in every second iteration. let me know which part you didn't understand. 

January 4, 2013 at 3:06 AM
Ken Whitesell said...

Actually, I would dispute the assertion that this is being done "in one pass". You're making two separate passes through the list - it's just that you're doing them concurrently and not consecutively.

January 4, 2013 at 6:41 AM
Anonymous said...

instead of checking length why not you just increment one pointer twice and other pointer only one. this would make your linked list middle element checking code simpler.

January 9, 2013 at 9:24 PM
Guido Diepen said...

I have to agree with Ken, you just just do two traversals within one loop.

January 11, 2013 at 4:43 AM
Javin @ prime number in Java said...

@Guido, Can you please elaborate? I think node.next() doesn't traverse the list it just like incrementing pointer, don't agree?

January 11, 2013 at 7:25 AM
Guido Diepen said...

@Javin: I understand it just increments the pointer. 

But as far as I can see, the code keeps track of two elements (i.e. pointers) in the loop: middle and current. 

So even though it is executed within one for-loop, I do see two traversals:
* current looping all the way till the end
* middle looping till the middle

That is why I agreed with the statement of Ken that I would not call this one pass. Could just be a word thing and that with one-pass here it is meant you are only allowed to use one for-loop.

January 18, 2013 at 1:54 PM
Anonymous said...

Ken and Guido.. Good Catch.. I had the same question when I read the article. As you said, if it is a wording issue(like using one for-loop), it clears my doubt.

- Durai

February 13, 2013 at 9:07 PM
rakeshudandakar said...

Hi,

The simple way to find the middle element is written below

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Set;

import javax.swing.text.html.HTMLDocument.Iterator;
import javax.xml.soap.Node;
public class test2 {


public static void main(String args[]) 
{

LinkedList l=new LinkedList();
l.add(2);
l.add(3);
l.add(9);
l.add(4);

java.util.Iterator i1=l.iterator();
java.util.Iterator i2=l.iterator();

int i=0;
int middle = 0;
while(i1.hasNext())
{
if(i==0)
{
i1.next();
i=1;

}
else if(i==1)
{
if(i1.hasNext())
{

i1.next();

middle=(Integer) i2.next();
i=0;
}
}
}
System.out.println("middle"+middle);



}

}

March 31, 2013 at 11:39 PM
Anonymous said...

This extra code:
if(length%2 == 1){
middle = middle.next();
}
is not required..because your code to find middle element will give the same result without this piece of code anyway

July 2, 2013 at 11:23 PM
Dan Kroll said...

Ken is correct. Unless I am missing something, this isn't one pass, it is 1.5. If you demand an answer for a single pass, a student should respond that it isn't possible and that only 1.5 is possible. The idea that answering this 'incorrectly' could have cost someone a job is slightly disconcerting.

October 9, 2013 at 4:47 PM
Anonymous said...

Guys please comment on my approach, I am also doing in 1.5 pass. Please suggest if it is efficient or can be improved ?

package my.data.structures;

class LlNode{
int data;
LlNode next;
LlNode prev;
}
class Linked{
LlNode start;
public Linked()
{
start = null;
}

public void insertLl(int d){
LlNode node = new LlNode();
node.data = d;
if (start == null)
{
start = node;
start.next = null;
start.prev = null;
}
else{
LlNode current;
LlNode previous;
current = start;
while(true){
previous = current;
if(current.next==null)
{
current.next = node;
node.prev = previous;
node.next = null;
return;
}
else{
current = current.next;
}
}
}
}

public void displayLl(){
LlNode current;
current = start;
while(current != null){
System.out.print(current.data+"---->");
current = current.next;
}
}

public void findmid() {
// TODO Auto-generated method stub
LlNode current;
LlNode mid;
current = start;
mid = start;
int midnode, i,j;
midnode = 1;
int cur; 
cur = 0;
i=0;j=0;
while(current != null){
if(cur==1)
{
System.out.println("\nMid Node is at : "+midnode);
return; 
}
else{
mid = mid.next;
midnode++;
for (i=0;i<2;i++){
if(current.next == null){
System.out.println("No mid, length is even");
return;
}
current = current.next;
}
if(current.next == null){
cur=1;
}
}

}

}
}

public class LinkedList{
public static void main(String[] args) {
Linked l = new Linked();
// TODO Auto-generated method stub
l.insertLl(1);
l.insertLl(2);
l.insertLl(3);
l.insertLl(4);
l.insertLl(5);
l.insertLl(6);
l.insertLl(7);
l.displayLl();
l.findmid();

}

}

October 19, 2013 at 4:24 PM
Anonymous said...

import java.util.LinkedList;


public class LinkedListTest {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub

LinkedList node = new LinkedList();
node.add(4);
node.add(5);
node.add(7);
node.add(10);
node.add(2);
node.add(1);
node.add(22);


LinkedListTest obj =new LinkedListTest();

float len = (float) node.size();
float midInd = 0 ;

if(obj.evenOdd(len))
{
midInd= len/2;
}else
{
midInd = (float) ((len/2)- 0.5);
}

int j = (int)midInd;
j = node.get(j);
System.out.print(midInd + " "+j);
}

public boolean evenOdd(float i)
{
if ( i % 2 == 0 )
{
return true;
}else
{
return false;
}



}

}

November 6, 2013 at 1:04 AM
Anonymous said...

The solution presented here obviously does more than one pass and hence isn't valid. It doesn't matter if all you do is chasing the pointers. You are still traversing 1.5 times and could just as well do a count run and then stop in the middle for the next one with the same effort.

A java LinkedList is a doubly linked list (http://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html) so the whole premise that you would be working on a singly linked list is wrong too. The correct solution would be to advance from both sides (front and back) of the doubly linked list simultaneously until you meet in the middle element (happens for uneven list length) or the next element matches the current element of the other (happens for even list lengths).

June 15, 2014 at 12:38 PM
Anonymous said...

public void middle(){
node slow=start.next;
node fast=start.next;
while(fast.next!=null)
{
slow=slow.next;
fast=fast.next.next;
}

System.out.println(slow.data);
}


10->9->8->7->6->5->4->3->2->1->

5

July 19, 2014 at 11:53 AM
Anup said...

if(length%2 == 1){
middle = middle.next();
}

Code is not required.
It works without that irrespective of even or odd number of nodes.

November 30, 2014 at 4:05 AM


Reference: http://javarevisited.blogspot.com/2012/12/how-to-find-middle-element-of-linked-list-one-pass.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值