举例:1,2,3,4,5,要找到倒数第2个节点,则
1,2,3,4,5
p q
p q=null
p,q相差2步,经过2步遍历之后,q到达终点, 此时p指向3,就是倒数第三个节点,那么p的下一个节点就是要找的节点。
设置两个指针p,q;p,q相差k步。
p,q同时前进,当q== null时,此时p所指向的节点就是倒数第k个节点。
剑指offer上只要求找出该节点。代码如下,代码中用slow表示p,fast表示q:
ListNode* findKthTail(ListNode* head, int k)
{
ListNode* slow = pListHead;
ListNode* fast = pListHead;
for (int i = 0; i < k; ++i) {
if (fast == nullptr) {
return nullptr;
} else {
fast = fast->next;
}
}
while (fast != nullptr) {
slow = slow->next;
fast = fast->next;
}
return slow;
}
如果要删除该节点,则在遍历的过程中用pre记录slow的前驱。
找到要被的删除的节点slow后要讨论:
1.如果slow是头节点,即pre=null,则直接返回p.next
2.否则,pre.next = slow.next
public ListNode removeNthFromEnd (ListNode head, int n) {
if (head == null) {
return null;
}
ListNode fast = head, slow = head, pre = null;
for (int i = 0; i < n; ++i) {
if (fast != null) {
fast = fast.next;
} else {
return head.next;
}
}
while (fast != null) {
fast = fast.next;
pre = slow;
slow = slow.next;
}
if (pre == null) {
return head.next;
}
pre.next = slow.next;
return head;
}