我们前几天已经学过了线性表:顺序表,链表和栈,但是只有理论知识是绝对不够的,我给大家找了一些很经典的题目,一定要做到立马有思路哦
(如果还有小可爱没有看过我的顺序表,链表和栈的知识点说明,请看↓
)
另外前一篇练习文章在下面,一定要把前一篇文章好好弄懂再看着一篇哦
目录
由于链表的知识很多,相关的好题更多,所以本文选取典中典的好题给大家把常见思路都见一见,并不能说包含所有但是学完肯定能应付很多题目
我们开始吧~~
1.1翻转链表

其实完全不用遍历到最后一个节点,把最后的换成新头然后往前走
因为我们在之前在单链表学过,单链表的结构决定了他就是不能很好的“倒车”,非常麻烦,还需要考虑指向的问题
有点小伙伴说那就弄成双向,是一个办法,但是人家给你一个单链表你非要硬做成双向...
最好的方法

从第一个链表经过我们的操作变成了下面这个
之后把tail(此时在NULL)变成cur,cur变成next保存的节点就可以了
(注意:这里tail一开始初始化成NULL并没有开辟空间所以空间复杂度还是O(1))
- struct ListNode* reverseList(struct ListNode* head){
- struct ListNode*tail=NULL,*cur=head,*next=head;
- while(cur)
- {
- next=cur->next;
- cur->next=tail;
- tail=cur;
- cur=next;
- }
- return tail;
- }
1.2 寻找中间节点

这个看起来是不是立马想到:分奇数偶数!!先把链表遍历然后记录节点个数返回个数/2的节点!!!
- struct ListNode* middleNode(struct ListNode* head){
- struct ListNode*tail=head;
- int count=0;
- while(tail)
- {
- count++;
- tail=tail->next;
- }
-
- for(int i=0;i
2;i++) - {
- head=head->next;
- }
- return head;
-
- }
这样做肯定可以啊,也很简洁
但是我们不能局限于写出来和我只能想到...
更优化的办法:快慢指针
快指针一次走两步,慢指针一次走一步,这样听起来好玄乎,举个例子看看

发现所有可能出现的情况都包含在内,如果本身链表为空,那slow自然就是NULL返回也直接是NULL
- struct ListNode* middleNode(struct ListNode* head){
- struct ListNode*fast=head,*slow=head;
- while(fast&&fast->next)
- {
- fast=fast->next->next;
- slow=slow->next;
- }
- return slow;
- }
1.3返回倒数第n个节点

根据上一个题目的思路,只需要每次fast先走k个,如果在走的过程中有fast==NULL,那么直接返回NULL,然后再fast和slow各走一步就可以了
- struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
- // write code here
- int count=0;
- struct ListNode*slow=pListHead,*fast=pListHead;
- while(k--)
- {
- if(fast)
- {
- fast=fast->next;
- }
- else
- {
- return NULL;
- }
- }
- while(fast)
- {
- fast=fast->next;
- slow=slow->next;
- }
- return slow;
- }
考虑到吸收效率的情况,今天还是只放三个题目,记得关注继续看下文哦~~