輸入一個鏈表,輸出該鏈表中倒數第k個節點。爲了符合大多數人的習慣,本題從1開始計數,即鏈表的尾節點是倒數第1個節點。例如,一個鏈表有6個節點,從頭節點開始,它們的值依次是1、2、3、4、5、6。這個鏈表的倒數第3個節點是值爲4的節點。
示例:
給定一個鏈表: 1->2->3->4->5, 和 k = 2.
返回鏈表 4->5.
解題思路:
- 第一時間想到的解法:
先遍歷統計鏈表長度,記爲 n ; - 設置一個指針走 (n-k) 步,即可找到鏈表倒數第 k 個節點。
使用雙指針則可以不用統計鏈表長度。
算法流程:
- 初始化: 前指針 former 、後指針 latter ,雙指針都指向頭節點 head 。
- 構建雙指針距離: 前指針 former 先向前走 k 步(結束後,雙指針 former 和 latter 間相距 k 步)。
- 雙指針共同移動: 循環中,雙指針 former 和 latter 每輪都向前走一步,直至 former 走過鏈表尾節點時跳出(跳出後, latter 與尾節點距離爲 k-1,即 latter 指向倒數第 k 個節點)。
- 返回值: 返回 latter 即可。
複雜度分析:
時間複雜度 O(N): N爲鏈表長度;總體看, former 走了N步, latter 走了 (N-k)步。
空間複雜度 O(1): 雙指針 former , latter 使用常數大小的額外空間。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
ListNode* former = head;
ListNode* latter = head;
while(k)
{
former = former->next;
k--;
}
while(former)
{
latter = latter->next;
former = former->next;
}
return latter;
}
};
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
if(head == NULL || k == 0)
{
return NULL;
}
ListNode* former = head;
ListNode* latter = head;
int i = 0;
while(former)
{
if(i>=k)
{
latter = latter->next;
}
former = former->next;
i++;
}
return latter;
}
};
參考
https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/