剑指offer22. 链表中的倒数第k个节点 P134
题目:输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是值为4的结点。
// 本题主要是鲁棒性检测 两个if条件的内容。第二个if不能用p!=NULL 是因为,p定义指的是最后一共节点,如果最后p是NULL(最后一共节点的下一个节点)了,就失去意义了。
ListNode *findK(ListNode *head, int k) {
if (head == NULL || k < 1) return 0;
ListNode *p = head; // 指向倒数第一个节点
for (int i = 0; i < k- 1; ++i) {
if (p -> m_pNext != NULL) p = p -> m_pNext; // 节点总数小于k
else return NULL;
}
ListNode *q = head; // 倒数第k个节点
while (p -> m_pNext != NULL) {
p = p -> m_pNext;
q = q -> m_pNext;
}
return q;
}
扩展:
求链表的中间节点:如果链表节点数是奇数,返回中间节点,否则返回中间两个节点任一个。
定义一个快指针一次走两步,一个慢指针一次走一步。快指针走到末尾慢指针指的就是答案
ListNode *find_mid(ListNode *head)
{ if(head == NULL) return NULL;
ListNode *slow, *fast;
slow = fast = head; /*快慢指针都指向第一个节点*/
while (fast != NULL && fast->next != NULL && fast->next->next != NULL) {
slow = slow->next; /*慢指针每次走一步*/
fast = fast->next->next; /*快指针每次走两步*/
}
return slow;
}