三:链表的中间结点
基本思路: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节点
}
因为这两个题都应用到了快慢指针,但实现的技巧不一样,所以单独写一篇博客,后续还有链表其他方向的典例,后续会陆续推出。