Interview question: How to quickly find the middle node of a singly linked list of unknown length?

Interview question: How to quickly find the middle node of a singly linked list of unknown length?

background

I came across an interview question by chance: How to quickly find the middle node of a singly linked list of unknown length?

method

The first thing I thought of was a very simple traversal method, and then I learned a method of fast and slow pointers.

common method

principle

The common method is very simple, first traverse the singly linked list to determine the length of the singly linked list. Then start from the head node and loop N/2 times again to find the middle node of the singly linked list.

The complexity of the algorithm is O(N+N/2)=O(3N/2).

the code
void common_found_List(Linklist *L,int len)
{
    
    
	Linklist *mid;
	int i = 0;
	Elemtype e;
	mid = L;
	len = len/2;
	while(i<=len)
	{
    
    
		mid = mid->next;
		i++;
	}
	e = mid->data;
	printf("The middle data of the list is :%d\n",e);
}

advanced method

Optimize the common search method→★★★Speed ​​and slow pointer★★★

principle

Set the two pointers p and mid to point to the head node of the singly linked list. Among them, the moving speed of p is twice that of mid. When *p points to the end node, *mid will also point to the middle node.

The complexity of the algorithm is O(N/2).

the code
void fast_slow_List(Linklist *L)
{
    
    
	Linklist *f,*mid;
	Elemtype e;

	f = L;
	mid = L;

	while(f->next)
	{
    
    
		if(f->next->next)
		{
    
    
			f = f->next->next;
			mid = mid->next;
		}
		else
		{
    
    
			f = f->next;
		}
	}
	e = mid->next->data;
	printf("The middle data of the list is :%d\n",e);
}

Experimental process and results

total code
//<库函数>
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<math.h>

//<相关参数的宏定义>
#define Len sizeof(Node)
#define N 20                              
typedef int Elemtype;

typedef struct Node
{
    
    
	Elemtype data;
	struct Node* next;
}Node;

typedef struct Node Linklist;

//功能函数
Linklist* Creat_L();
void Out_Linklist(Linklist *h);
void fast_slow_List(Linklist *L);
void common_found_List(Linklist *L,int len);
int Length_list(Linklist *L);

void main()
{
    
    
	Linklist *L;
	int k ;
	int i ;
	int len;
	Elemtype x;

	printf("		《 Welcome to use the founction 》\n");
	printf("	    The founction can offer following service\n");
	printf("		*******Please first Initlist*******\n\n");
	printf("		1、Initlist          ->创建单链表\n");
	printf("		2、Insertlist        ->输出链表长度操作\n");
	printf("		3、common_Foundlist  ->普通方法查找中间元素操作\n");
	printf("		4、fast_Foundlist    ->高级方法查找中间元素操作\n");
	printf("		0、Exitlist          ->退出操作\n\n\n");
	printf("        Please choose following digital:1、2、3、0\n");
	printf("               Finish your idea!!!!!!\n");
	do
	{
    
    
		printf("\n\nPlease Input your choice:");
		scanf("%d",&k);
		switch(k)
		{
    
    
		case 1:
			{
    
    
				L = Creat_L(); 
				Out_Linklist(L);
			}break;
		case 2:
			{
    
    
				len = Length_list(L);
				printf("The length of the list is:%d\n",len);
			}break;
		case 3:
			{
    
    
				len = Length_list(L);
				common_found_List(L,len);
			}break;
		case 4:
			{
    
    
				fast_slow_List(L);
				Out_Linklist(L);
			}break;
		}
	}while(k!=0);
}

// <随机创建单链表>
Linklist* Creat_L()
{
    
    
	int count = 0;
	Linklist *h,*p,*s;
	Elemtype x;
	h = (Node*)malloc(Len);
	h->next = NULL;	
	p = h;
	//printf("Please Enter the FIRST Node data: ");
	//scanf("%d",&x);
	while(count < N)                          //假设终止条件
	{
    
    
		x = rand() % 50;                      //随机生成各节点,创建单链表
		s = (Node*)malloc(Len);	
		s->data = x;                          //赋值		
		s->next = NULL;
		p->next = s;
		p = s;	
		//printf("Please Enter the NEXT  Node data: ");
		//scanf("%d",&x);
		count++;
	}
	return h;
}

//<输出函数>
void Out_Linklist(Linklist *h)
{
    
    
	Linklist *p;
	p  = h->next;
	printf("Output Linklist:\n");
	while(p)
	{
    
    
		if(p->next!=NULL)
		{
    
    
			printf("%d -> ",p->data);
			p = p->next;
		}
		else
		{
    
    
			printf("%d",p->data);
			p = p->next;
		}
	}
}

// <快慢指针查找函数:使用快慢指针查找中间值的操作,时间复杂度为O(N/2)>
void fast_slow_List(Linklist *L)
{
    
    
	Linklist *f,*mid;
	Elemtype e;

	f = L;
	mid = L;

	while(f->next)
	{
    
    
		if(f->next->next)
		{
    
    
			f = f->next->next;
			mid = mid->next;
		}
		else
		{
    
    
			f = f->next;
		}
	}
	e = mid->next->data;
	printf("The middle data of the list is :%d\n",e);
}

//<长度函数>
int Length_list(Linklist *L)
{
    
    
	int count = 0;
	Linklist *p;

	p = L;
	while(p->next)
	{
    
    
		p = p->next;
		count++;
	}
	//printf("The length of the list is:%d\n",count);
	return count;
}

// <普通方法函数>
void common_found_List(Linklist *L,int len)
{
    
    
	Linklist *mid;
	int i = 0;
	Elemtype e;
	mid = L;
	len = len/2;
	while(i<=len)
	{
    
    
		mid = mid->next;
		i++;
	}
	e = mid->data;
	printf("The middle data of the list is :%d\n",e);
}
operation result

insert image description here

Summarize

Using the fast and slow pointer algorithm to find the intermediate nodes of the singly linked list is about 3 times faster than the common algorithm. Of course, there is no speed difference in this example. When there are many elements, there will be a more obvious gap.

In addition, advanced methods will add points during your interview! ! ! ! ! !

Guess you like

Origin blog.csdn.net/MZYYZT/article/details/113437641