三:链表的中间结点
基本思路:1)因为链表非空,所以不用断言
2)使用快慢指针为最优解,定义两个指针fast 和 slow
fast一次走两步,slow一次走一步。
3)分情况
i若链表长度为奇数时
此时返回slow即为所求
ii若为偶数时
可见,当fast指向为空时,slow的位置即为所求。
代码展示
- /**
- * Definition for singly-linked list.
- * struct ListNode {
- * int val;
- * struct ListNode *next;
- * };
- */
-
- struct ListNode* middleNode(struct ListNode* head){
- struct ListNode* slow,*fast;//创建快慢指针
- slow = fast = head;//指向的都是头节点
- while(fast && fast->next)//这里注意fast必须在前,
- //因为根据&&的性质,前面为假,后面的就不看了,fast在后就会使得为奇数的情况报错
- {
- slow = slow->next;//slow一次前进一个
- fast = fast->next->next;//fast前进两个
- }
- return slow;//slow所指的即为所求
- }
四:链表中倒数第k个节点
基本思路:1)如果链表为空,那就返回NULL
2)创建快慢指针,但快指针先走k步,之后快慢指针一起移动,那么,终止循环的条件是fast==NULL
3)如果给定的k值超过了链表的长度,会使得fast成为野指针,所以要判断fast是否在先走的情况下成为野指针。
画图:
代码展示:
- struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
- // write code here
- struct ListNode* slow,*fast;//创建快慢指针
- slow = fast = pListHead;//指针初始指向头节点
- while(k--)//fast先走k步
- {
- if(fast == NULL)//给定的k的值超过了链表的长度
- {
- return NULL;//返回NULL
- }
- fast = fast->next;//更新fast
- }
- while(fast)//fast为空结束循环
- {
- slow = slow->next;
- fast = fast->next;//fast和slow都走一步
- }
- return slow;//返回slow节点
- }
因为这两个题都应用到了快慢指针,但实现的技巧不一样,所以单独写一篇博客,后续还有链表其他方向的典例,后续会陆续推出。