面试中常见的链表题目

最近参加面试遇到的一些常见的单链表题目,总结思路和实现代码。

1.单链表的反序

2.给单链表建环

3.检测单链表是否有环

4.给单链表解环

5.检测两条链表是否相交

6.不输入头节点,删除单链表的指定节点(只给定待删除节点指针)

7.合并两个有序链表


1.单链表的反序

01 //逆转链表,并返回逆转后的头节点 
02 node* reverse(node *head) 
03
04     if(head == NULL || head->next == NULL) 
05     
06         returnhead; 
07     
08     node *cur = head; 
09     node *pre = NULL; 
10     node *tmp; 
11     while(cur->next) 
12     
13         tmp = pre; 
14         pre = cur; 
15         cur = cur->next; 
16         pre->next = tmp;                  //操作pre的next逆转 
17     
18     cur->next = pre;                     //结束时,操作cur的next逆转 
19     returncur; 
20 }
01 //方法二
02 node *reverse(node *head)
03 {
04     node *p, *q, *r;
05      
06     p = head;
07     q = p->next;
08      
09     while(q != NULL)
10     {
11         r = q->next;
12         q->next = p;
13         p = q;
14         q = r;
15     }
16  
17     head->next = NULL;
18     head = p;
19      
20     return head;
21 }

2.给单链表建环

01 //给单链表建环,让尾指针,指向第num个节点,若没有,返回false 
02 bool bulid_looplink(node *head, intnum) 
03
04     node *cur = head; 
05     node *tail = NULL; 
06     inti = 0; 
07     if(num <= 0 || head == NULL) 
08     
09         returnfalse
10     
11     for(i = 1; i < num; ++i) 
12     
13         if(cur == NULL) 
14         
15             returnfalse
16         
17         cur = cur->next; 
18     
19     tail = cur; 
20     while(tail->next) 
21     
22         tail = tail->next; 
23     
24     tail->next = cur; 
25     returntrue
26 }

3.检测单链表是否有环

01 //检测单链表是否有环,快慢指针 
02 booldetect_looplink(node *head) 
03
04     node *quick_node = head->next, *slow_node = head; 
05     if(head == NULL || head->next == NULL) 
06     
07         returnfalse
08     
09     while(quick_node != slow_node) 
10     
11         if(quick_node == NULL || slow_node == NULL) 
12             break
13         quick_node = quick_node->next->next; 
14         slow_node = slow_node->next; 
15     
16     if(quick_node != NULL && slow_node != NULL)    //非尾节点相遇 
17         returntrue
18     returnfalse
19 }

4.给单链表解环

ps:为了增加节点位图的效率,本应使用hash或则红黑树,这里不造车了,直接用 set容器

01 //找到有环节点,并解环,找到并解环,返回true,无环,返回false 
02 //思路:先找到环节点:被2个节点指向的节点(一定有环的条件)ps:不考虑中间环,因为只有一个next节点,只可能是尾环 
03 boolunloop_link(node *head) 
04
05     set<node *> node_bitmap;        //node的地址位图 
06     unsigned intnum = 0; 
07     node *cur = head, *pre = NULL; 
08     while(cur != NULL) 
09     
10         if(!node_bitmap.count(cur) )              //该节点未被遍历过 
11         
12             node_bitmap.insert(cur); 
13             ++num; 
14         
15         else                              //指向已被遍历过的节点,此时pre节点为尾节点 
16         
17             pre->next = NULL; 
18             returntrue
19         
20         pre = cur; 
21         cur = cur->next; 
22     
23     returnfalse
24 }
5.检测两条链表是否相交

01 //检测两条链表是否相交,是则返回第一个交点,否则返回NULL 
02 //思路:把2个链表各遍历一遍,记下长度length1和length2,若2者的尾节点指针相等,则相交。 
03 //       之后再把长的链表从abs(len1-len2)的位置开始遍历,第一个相等的指针为目标节点 
04 node* detect_intersect_links(node *first_link, node *second_link) 
05
06     intlegnth1 = 1, length2 = 1, pos = 0; 
07     node *cur = NULL, *longer_link = first_link, *shorter_link = second_link; 
08     if(first_link == NULL || second_link == NULL) 
09     
10         returnNULL; 
11     
12     while(first_link->next || second_link->next)     //遍历2个链表 
13     
14         if(first_link->next) 
15         
16             first_link = first_link->next; 
17             ++legnth1; 
18         }
19         if(second_link->next)
20         {
21             second_link = second_link->next;
22             ++length2;
23         }
24     }
25     if(first_link != second_link)                 //比较尾节点 
26     {
27         return NULL;
28     }
29     pos = legnth1 - length2; 
30     if(legnth1 < length2)                  //保证 longer_link为长链表 
31     
32         pos = length2 - legnth1; 
33         cur = longer_link; 
34         longer_link = shorter_link; 
35         shorter_link = cur; 
36     
37     while(pos-- > 0) 
38         longer_link = longer_link->next; 
39     while(longer_link || shorter_link) 
40     
41         if(longer_link == shorter_link)                  //找到第一个交点 
42         
43             returnlonger_link; 
44         
45         longer_link = longer_link->next; 
46         shorter_link = shorter_link->next; 
47     
48     returnNULL; 
49 }

6.不输入头节点,删除单链表的指定节点(只给定待删除节点指针)

01 //无头节点,随机给出单链表中一个非头节点,删除该节点,当传入空节点,或者尾节点时,返回false 
02 //思路:由于没有头节点,非循环单链表,无法获取目标节点的前节点,所以只能把它的next节点数据前移,并删除next节点 
03 //ps:当传入节点为尾节点,无法用此方法删除 
04 boolwithouthead_delete_node(node *target_node) 
05
06     node *cur = NULL; 
07     if(target_node == NULL || target_node->next == NULL)   //空节点或者尾节点,失败 
08     
09         returnfalse
10     
11     cur = target_node->next; 
12     target_node->name = cur->name; 
13     target_node->next = cur->next; 
14     deletecur; 
15     returntrue
16 }

7.合并两个有序链表

001 /*
002 递归实现:
003 ①算法思想:
004 递归终止条件:若head1为空,返回head2指针(head);若head2为空,返回head1指针(head)
005 递归过程:
006  
007 1 若head1->data>head2->data;  head 指针应该指向head2所指向的节点,而且head->next应该指向head1和head2->next两个链表的合成序列的头指针;
008  
009 2 否则head 指针应该指向head1所指向的节点,而且head->next应该指向head->next和head2两个链表的合成序列的头指针;
010 */
011 #include <iostream>
012 using namespace std;
013  
014 /*节点的类定义*/
015 class Node
016 {
017 public:
018     int data;
019     Node *next;
020     Node(int data)
021     {
022         this->data = data;
023     }
024 };
025  
026 /*链表的类定义*/
027 class LinkedList
028 {
029 public:
030     Node *head;
031  
032     /*用一个整形数组作为参数的构造函数*/
033     LinkedList(int array[])
034     {
035         head = new Node(array[0]);
036         Node *temp = head;
037         int i;
038         for( i = 1; i < 3; i++ )
039         {
040             temp->next = new Node(array[i]);
041             temp = temp->next;
042         }
043          
044         temp->next = NULL;
045     }
046 };
047  
048 /*递归的合并两个有序链表*/
049 Node * mergeLinkedList(Node *head1, Node *head2)
050 {
051     Node *p = NULL;
052      
053     if(head1 == NULL && head2 == NULL)
054         return p;
055     else if(head1 == NULL)
056         return head2;
057     else if(head2 == NULL)
058         return head1;
059     else
060     {
061         if(head1->data < head2->data)
062         {
063             p = head1;
064             p->next = mergeLinkedList(head1->next, head2);
065         }
066         else
067         {
068             p = head2;
069             p->next = mergeLinkedList(head1, head2->next);
070         }
071          
072         return p;
073     }
074 }
075  
076 /*打印链表的所有元素*/
077 void printList(Node *head)
078 {
079     Node *temp = head;
080     while(temp != NULL)
081     {
082         cout<<temp->data<<"  ";
083         temp = temp->next;
084     }
085 }
086  
087 int main()
088 {
089     int array1[3] = {2,5,8};
090     int array2[3] = {1,6,7};
091      
092     /*构造两个有序链表--list1和list2*/
093     LinkedList list1(array1);
094     LinkedList list2(array2);
095  
096     /*递归的将这两个有序链表合并成一个有序链表*/
097     Node *new_head = mergeLinkedList(list1.head, list2.head);
098  
099     /*打印有序链表*/
100     printList(new_head);
101  
102     return 0;
103 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yongjunhe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值