博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
链表笔试面试题
阅读量:5245 次
发布时间:2019-06-14

本文共 8187 字,大约阅读时间需要 27 分钟。

1 给定单链表,检测是否有环。

      使用两个指针p1,p2从链表头开始遍历,p1每次前进一步,p2每次前进两步。如果p2到达链表尾部,说明无环,否则p1、p2必然会在某个时刻相遇(p1==p2),从而检测到链表中有环。

1 struct Node 2 { 3     int val; 4     Node * next; 5     Node(int _val=0,Node * _next=NULL) 6     { 7         val = _val; 8         next = _next; 9     }10 };11 12 bool isLinklistHasLoop(Node * head)13 {14     Node * p1 = head, *p2 = head;15     while(true)16     {17         if (p1 == NULL)18         {19             return false;20         }21         else22         {23             p1 = p1->next;24         }25         if (p2 == NULL || p2->next == NULL)26         {27             return false;28         }29         else30         {31             p2 = p2->next->next;32         }33         if (p1 == p2)34         {35             return true;36         }37     }38 }

 

2 给定两个单链表(head1, head2),检测两个链表是否有交点,如果有返回第一个交点。

如果head1==head2,那么显然相交,直接返回head1。否则,分别从head1,head2开始遍历两个链表获得其长度len1与len2,假设len1>=len2,那么指针p1由head1开始向后移动len1-len2步,指针p2=head2,下面p1、p2每次向后前进一步并比较p1p2是否相等,如果相等即返回该结点,否则说明两个链表没有交点。

1 int getLinklistLength(Node * head) 2 { 3     int cnt = 0; 4     Node * p = head; 5     while(head != NULL) 6     { 7         cnt++; 8         head = head->next; 9     }10     return cnt;11 }12 13 Node * getFirstIntersectNode(Node * head1,Node * head2)14 {15     if (head1 == head2)16     {17         return head1;18     }19     int len1 = getLinklistLength(head1);20     int len2 = getLinklistLength(head2);21     Node * p1 = head1, * p2 = head2;22     if (len1 >= len2)23     {24         for (int i=1; i<=len1-len2; i++)25         {26             p1 = p1->next;27         }28     }29     else30     {31         for (int i=1; i<=len2-len1; i++)32         {33             p2 = p2->next;34         }35     }36     while(p1 != NULL && p2 != NULL)37     {38         if (p1 == p2)39         {40             return p1;41         }42         p1 = p1->next;43         p2 = p2->next;44     }45     if (p1==NULL || p2==NULL)46     {47         return NULL;48     }49 }

 

3 给定单链表(head),如果有环的话请返回从头结点进入环的第一个节点。

        运用题一,我们可以检查链表中是否有环。如果有环,那么p1p2重合点p必然在环中。从p点断开环,方法为:p1=p, p2=p->next, p->next=NULL。此时,原单链表可以看作两条单链表,一条从head开始,另一条从p2开始,于是运用题二的方法,我们找到它们的第一个交点即为所求。

 

4 只给定单链表中某个结点p(并非最后一个结点,即p->next!=NULL)指针,删除该结点。

       首先是放p中数据,然后将p->next的数据copy入p中,接下来删除p->next即可。

1 void deleteNode(Node * node)2 {3     Node * nextNode = node->next;4     node->val = nextNode->val;5     node->next = nextNode->next;6     delete nextNode;7 }

 

 

5 只给定单链表中某个结点p(非空结点),在p前面插入一个结点。

        办法与前者类似,首先分配一个结点q,将q插入在p后,接下来将p中的数据copy入q中,然后再将要插入的数据记录在p中。

1 template
2 void tmpSwap(T & a,T & b) 3 { 4 T tmp = a; 5 a = b; 6 b = tmp; 7 } 8 9 void insertNode(Node * curNode,Node * newNode)10 {11 newNode->next = curNode->next;12 curNode->next = newNode;13 tmpSwap(curNode->val,newNode->val);14 }

 

 

6 单链表的逆置

两种方法,非递归和递归

1 void loopReverseLinklist(Node * & head) 2 { 3     Node * preNode = head; 4     Node * curNode = preNode->next; 5     Node * nextNode = NULL; 6     while(curNode != NULL) 7     { 8         nextNode = curNode->next; 9         curNode->next = preNode;10         preNode = curNode;11         curNode = nextNode;12     }13     head->next = NULL;14     head = preNode;15 }16 17 void dfsReverseLinklist(Node * & head,Node * curNode)18 {19     if (curNode == NULL || curNode->next == NULL)20     {21         head = curNode;22         return;23     }24     Node * nextNode = curNode->next;25     dfsReverseLinklist(head,nextNode);26     nextNode->next = curNode;27     curNode->next = NULL;28 }

另外,带返回值的方法如下:

1 Node * loopReverse(Node * node) 2 { 3     if (node == NULL || node->next == NULL) 4     { 5         return node; 6     } 7     Node * prePt = node, * curPt = prePt->next; 8     Node * nextPt = NULL; 9     while(curPt != NULL)10     {11         nextPt = curPt->next;12         curPt->next = prePt;13         prePt = curPt;14         curPt = nextPt;15     }16     node->next = NULL;17     return prePt;18 }19 20 21 Node * dfsReverse(Node * node)22 {23     if (node == NULL || node->next == NULL)24     {25         return node;26     }27     Node * nextNode = dfsReverse(node->next);28     node->next->next = node;29     node->next = NULL;30     return nextNode;31 }

 

7 单链表找出中间节点

单链表的一个比较大的特点用一句广告语来说就是“不走回头路”,不能实现随机存取(random access)。如果我们想要找一个数组a的中间元素,直接a[len/2]就可以了,但是链表不行,因为只有a[len/2 - 1] 知道a[len/2]在哪儿,其他人不知道。因此,如果按照数组的做法依样画葫芦,要找到链表的中点,我们需要做两步(1)知道链表有多长(2)从头结点开始顺序遍历到链表长度的一半的位置。这就需要1.5n(n为链表的长度)的时间复杂度了。有没有更好的办法呢?有的。想法很简单:两个人赛跑,如果A的速度是B的两倍的话,当A到终点的时候,B应该刚到中点。这只需要遍历一遍链表就行了,还不用计算链表的长度。

1 Node * findMidNode(Node * head) 2 { 3     if (head == NULL || head->next == NULL) 4     { 5         return head; 6     } 7     Node * p1 = head, * p2 = head; 8     while(true) 9     {10         if (p2->next != NULL && p2->next->next != NULL)11         {12             p2 = p2->next->next;13             p1 = p1->next;14         }15         else16         {17             break;18         }19     }20     return p1;21 }

8 已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序。(保留所有结点,即便大小相同)

两种方法,非递归和递归

1 Node * loopMergeLinklist(Node * head1,Node * head2) 2 { 3     if (head1 == NULL && head2 != NULL) 4     { 5         return head2; 6     } 7     if (head1 != NULL && head2 == NULL) 8     { 9         return head1;10     }11     if (head1 == NULL && head2 == NULL)12     {13         return NULL;14     }15     Node * p1 = head1, * p2 = head2;16     Node * newLinklist, * pNode;17     if (head1->val <= head2->val)18     {19         newLinklist = head1;20         pNode = head1;21         p1 = p1->next;22     }23     else24     {25         newLinklist = head2;26         pNode = head2;27         p2 = p2->next;28     }29     while(p1 != NULL && p2 != NULL)30     {31         if (p1->val <= p2->val)32         {33             pNode->next = p1;34             p1 = p1->next;35         }36         else37         {38             pNode->next = p2;39             p2 = p2->next;40         }41         pNode = pNode->next;42     }43     if (p1 != NULL)44     {45         pNode->next = p1;46     }47     else48     {49         pNode->next = p2;50     }51     return newLinklist;52 }53 54 Node * dfsMergeLinklist(Node * head1,Node * head2)55 {56     if (head1 == NULL)57     {58         return head2;59     }60     if (head2 == NULL)61     {62         return head1;63     }64     Node * newLinklist = NULL;65     if (head1->val < head2->val)66     {67         newLinklist = head1;68         newLinklist->next = dfsMergeLinklist(head1->next,head2);69     }70     else71     {72         newLinklist = head2;73         newLinklist->next = dfsMergeLinklist(head1,head2->next);74     }75     return newLinklist;76 }

 

 

9 有一个链表L,其每个节点有2个指针,一个指针next指向链表的下个节点,另一个random随机指向链表中的任一个节点,可能是自己或者为空,写一个程序,要求复制这个链表的结构并分析其复杂性

这个题目的方法很巧妙,将两个链表连接起来形成一个链表,设置好random指针后再将两个链表分割开来。

1 ComplexNode * copyRndList(ComplexNode * head) 2 { 3     ComplexNode * newHead = NULL; 4     ComplexNode * newCurPtr = NULL; 5     ComplexNode * curPtr = head; 6     while(curPtr != NULL) 7     { 8         if (newHead == NULL) 9         {10             newHead = new ComplexNode;11             newHead->nextPtr = curPtr->nextPtr;12             newHead->val = curPtr->val;13             curPtr->nextPtr = newHead;14         }15         else16         {17             newCurPtr = new ComplexNode;18             newCurPtr->nextPtr = curPtr->nextPtr;19             newCurPtr->val = curPtr->val;20             curPtr->nextPtr = newCurPtr;21         }22         curPtr = curPtr->nextPtr->nextPtr;23     }24     curPtr = head;25     while(curPtr != NULL)26     {27         if (curPtr->randPtr != NULL)28         {29             curPtr->nextPtr->randPtr = curPtr->randPtr->nextPtr;30         }31         else32         {33             curPtr->nextPtr->randPtr = NULL;34         }35         curPtr = curPtr->nextPtr->nextPtr;36     }37     curPtr = head;38     ComplexNode * dst = curPtr->nextPtr;39     while(curPtr != NULL)40     {41         ComplexNode * tmp = dst->nextPtr;42         curPtr->nextPtr = tmp;43         if (tmp)44         {45             dst->nextPtr = tmp->nextPtr;46         }47         curPtr = curPtr->nextPtr;48         dst = dst->nextPtr;49     }50     return newHead;51 }

 

转载于:https://www.cnblogs.com/shenshanxiaoyao/archive/2012/09/10/2678704.html

你可能感兴趣的文章
Java多线程系列——原子类的实现(CAS算法)
查看>>
安装Pygame和pip的艰辛之路
查看>>
Hibernate的实体类为什么需要实现 java.io.Serializable 接口
查看>>
在Ubuntu下配置Apache多域名服务器
查看>>
多线程《三》进程与线程的区别
查看>>
Min Stack
查看>>
老鸟的Python入门教程
查看>>
Ubuntu下非常给力的下载工具--uget+aria2
查看>>
Nginx配置
查看>>
棋盘覆盖问题
查看>>
vs2003无法调试 解决方法收藏
查看>>
.net-一般处理程序及生命周期
查看>>
linux sed命令
查看>>
[Cycle.js] Making our toy DOM Driver more flexible
查看>>
LeetCode 160. Intersection of Two Linked Lists
查看>>
html标签的嵌套规则
查看>>
10个实用的但偏执的Java编程技术
查看>>
sql语句查询出数据重复,取唯一数据
查看>>
GitHub上史上最全的Android开源项目分类汇总
查看>>
后台运行命令:&amp;和nohup command &amp; 以及关闭、查看后台任务
查看>>