【第21期】观点:人工智能到底用 GPU?还是用 FPGA?

面试数据结构篇—单链表常考点汇总

原创 2013年12月05日 17:44:28

单链表是最基本的数据结构,由于其简单的构造以及相关操作代码的简短,特别受面试官的青睐,面试官可以通过在短短的15分钟内让你写出单链表的操作,而对你的代码能力进行判断。所以掌握单链表是重中之重,对常考的知识点必须熟记于心,能够快速的写出来,并且bug-free。


单链表的定义

常见的定义方式如下:

 // Definition for singly-linked list.
 struct ListNode {
     int val;
     ListNode *next;
     ListNode(int x) : val(x), next(NULL) {}
};
从上述代码中可以看出,单链表包含数据以及指向下一个节点的指针,形象化的表示如下图1所示:

               
                                    图1: 单链表图(感谢第七城市提供)

单链表不一定有头结点,但是一定会有一个头指针head。


单链表常见面试题

面试题目录:

1:就地逆转单链表

2:检测单链表是否有环

3:判断两个单链表是否有交点,如果有交点,求交点

4:在O(1)时间内删除链表内的某一结点

5:如果单链表有环,求环的长度以及入环点

(一)就地逆转单链表

  经典做法:设定三个指针,一个是pre(指向前一个结点),一个是current(指向当前结点),一个next(指向下一个结点),然后三个指针同时往右移,并且同时修改指针指向的位置

//reverse the single-list in place
//@author: zhang haibo
//@time: 2013-12-5
ListNode* Reverse_Single_List(ListNode* head)
{
	 //check the head is or not NULL
	 if(head == NULL)
	 	   return head;
	 //the head of the reverse list
	 ListNode* reverseHead = NULL;
	 //current listnode
	 ListNode* current = head;
	 //the previous listnode of current listnode
	 ListNode* pre = NULL;
	 while(current != NULL)
	 {
	 	   ListNode* next = current->next;
	 	   if(next == NULL)
	 	   	   reverseHead = current;
	 	   current->next = pre;
	 	   pre = current;
	 	   current = next;
	 }
	 
	 return reverseHead;
}

(二)检测单链表是否有环

经典做法:设定两个指针,一个快指针,一个慢指针,快指针一次走两步,慢指针一次走一步,如果两个指针相遇,说明肯定存在环,如果没有环,则扫描到链表尾节点就退出了。

//check the singly-list whether or not has cycle
//@author: zhang haibo
//@time: 2013-12-5
bool Is_Exist_Cycle(ListNode* head)
{
	 ListNode* slow = head;
	 ListNode* fast = head;
	 while(fast != NULL && fast->next != NULL)
	 {
	 	   slow = slow->next;
	 	   fast = fast->next->next;
	 	   if(slow == fast)
	 	   	   return true;
	 }
	 
	 return false;
}

(三)判断两个单链表是否有交点,如果有交点,求交点

经典做法:判断两个链表的尾节点是否相同,如果相同则必存在交点,如果不相同,则不存在交点。具体的做法是,指向两个链表的指针p1和p2分别走到末尾,并且求出两个链表的长度了L1和L2,判断p1和p2是否相同,不相同则没有交点,直接返回即可,如果相同,则存在交点,设定p1和p2指向头结点,长链表先走abs(L1-L2)步,然后两个链表共同走即可。

//check two lists have intersection or not.
//@author: zhang haibo
//@time: 2013-12-5
bool Is_Exist_Intersection(ListNode* list1, ListNode* list2, ListNode* &result)
{
	 if(list1 == NULL || list2 == NULL)
	    return false;
	 ListNode* p1 = list1;
	 ListNode* p2 = list2;
	 int length_of_list1 = 1;
	 int length_of_list2 = 1;
	 while(p1->next != NULL)
	 {
	 	   p1 = p1->next;
	 	   ++length_of_list1;
	 }
	 while(p2->next != NULL)
	 {
	 	   p2 = p2->next;
	 	   ++length_of_list2;
	 }
	 
	 //not have the intersection
	 if(p1 != p2)
	 	   return false;
	 
	 //have the intersection
	 p1 = list1, p2 = list2;
	 if(length_of_list1 < length_of_list2)
	 {
	 		 p1 = list2;
	 		 p2 = list1;
	 }
	 	
	 //p1 goes forward dis steps
	 int dis = abs(length_of_list1 - length_of_list2);
	 while(dis--)
	 	   p1 = p1->next;
	 //p1 and p2 goes forward	in the same time
	 while(p1 != p2 )
	 {
	     p1 = p1->next;
	     p2 = p2->next;
	 }
	 
	 //set the result
	 result = p1;
	 
	 return true;
}

(四)在O(1)时间内删除链表内的某一结点

1)如果此节点是尾节点,则必须从头进行扫描到尾部节点前一个节点,进行删除,耗费N-1时间。

2)如果此节点是内部节点,则删除此节点的下一个节点,并且交换两个节点的数据即可,耗费1时间。

总体而言,假设链表的长度为N,总共的时间复杂度为(1/N)*(N-1)+(N-1/N)*1 = 1

//delete one node in the list
//@author: zhang haibo
//@time: 2013-12-5
ListNode* Delete_Node(ListNode* head, ListNode* deletedNode)
{
    if(head == NULL || deletedNode == NULL)
	   return head;
    //if deletedNode is the head of the list
    if(head == deletedNode)
    {
	   head = head->next;
	   return head;
    }
    //not the tail	   
    if(deletedNode->next != NULL)
    {
   	   ListNode* next = deletedNode->next;
   	   deletedNode->val = next->val;
   	   deletedNode->next = next->next;
   	   next = NULL;
    }
    else//the tail
    {
   	   ListNode* current = head;
   	   while(current->next != deleteNode)
   	       current = current->next;
   	   current->next = NULL;
    }
    return head;
}

(五)如果单链表有环,求环的长度以及入环点

 带环链表有如下几点性质,这里不再证明,请找相关资料查看:

1:快指针(每次走两步)和慢指针(每次走一步)肯定会在第一圈相遇

2:相遇点到入环点 和  链表头指针到入环点 的距离是相同的。

//find the entrance point and 
// calculate the length of cycle
//@author: zhang haibo
//@time:  2013-12-5
ListNode* Find_Loop_Port(ListNode* head, int& length)
{
	  length = 0;
	  if(head == NULL)
	  	  return NULL;
	  
	  ListNode* slow = head;
	  ListNode* fast = head;
	  while(fast != NULL && fast->next != NULL)
	  {
	  	  fast = fast->next->next;
	  	  slow = slow->next;
	  	  ++length;
	  }
	  
	  //no cycle
	  if(fast == NULL || fast->next == NULL)
	  {
	  	  length = 0;
	  	  return NULL;
	  }
	  
	  //set slow point to the start head
	  slow = head;
	  while(slow != fast)
	  {
	  	  slow = slow->next;
	  	  fast = fast->next;
	  	  ++length;
	  }
	  
	  return slow;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

面试题—数据结构之单链表详述(基本篇2)

下面也是关于单链表的操作问题,实现单链表的逆置,关于这个问题,最容易想到的方法是遍历一遍链表,利用一个辅助指针,存储遍历过程中当前指针指向下一个元素,然后将当前节点元素的指针反转,利用已经存在存储的指...

数据结构 - 反转单链表的递归算法(C++)

#include &lt;iostream&gt; #define NULL 0 using namespace std; struct Node { char data; Node* next; }; Node* create() { Node* head = NULL; Node* rear = head; Node* p; // The pointer points to the new created node. char tmp; do { cout &lt;&lt; "Ple

面试题—数据结构之单链表详述(基本篇)

单链表的结构是数据结构中最简单的,它的每一个节点只有一个指向后一个节点的指针。 单链表节点的定义: [cpp] view plaincopyprint? typedef ...

笔试面试常考数据结构-单链表常用操作编程实现

单链表是笔试以及面试手写代码中常考的数据结构之一。下面实现了单链表的常见操作:创建单链表、删除节点、打印单链表(包括正向打印以及逆向打印)、反转单链表、找出单链表的倒数第K个节点、合并两个有序单链表等操作。 <span style="font-family: KaiTi_GB2312; fo

面试题—数据结构之单链表详述(基本篇)

单链表的结构是数据结构中最简单的,它的每一个节点只有一个指向后一个节点的指针。单链表节点的定义:typedef struct node { int data; //节点内容 node *ne...

数据结构 - 返回单链表的中间结点

采用双指针的方法查找: 使用两个指针来遍历该链表,一个一次读2个结点,另一个一次读1个结点。当第一个指针到达末尾的时候,第二个指针所在的位置就是目标结点。注意,这里隐含着一个问题就是,链表长度奇偶的问题。

面试题—数据结构之单链表详述(基本篇3)

单链表的正向排序,就是插入数据时就按从小到大排序。 代码有注释很容易理解的: [cpp] view plaincopyprint? //单链表的正向排序  node *Ins...

数据结构 - 判断单链表是否有环(C++)

设置两个指针(slow和fast),初始值都指向链表头,slow每次前进一步,fast每次前进二步。如果链表存在环,则fast必定先进入环,而slow后进入环,且两个指针必定相遇。(当然,fast先行到达链表尾部[NULL],则为无环链表)程序如下: <pre

数据结构和算法设计专题之---判断单链表中是否有环,环的长度,环的入口节点

题目: 给定一个单链表,只给出头指针head: 1、如何判断是否存在环? 2、如何知道环的长度? 3、如何找出环的连接点在哪里? 4、带环链表的长度是多少? 解法: <span style="font-size: 14px; color: #

程序员面试宝典 C13数据结构基础 13.1 单链表

单链表单链表的建立单链表的测长单链表的打印单链表删除结点单链表插入结点单链表排序我把问题看得太复杂了,用了太多的指针,而且排序的时候还交换了节点。 书上的例子就简单多了: 首先获取链表长度 ...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)