剑指 Offer 22. 链表中倒数第k个节点
Posted 是七喜呀!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指 Offer 22. 链表中倒数第k个节点相关的知识,希望对你有一定的参考价值。
题目链接: 链表中倒数第k个节点
有关题目
输入一个链表,输出该链表中倒数第k个节点。
为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,
它们的值依次是 1、2、3、4、5、6。
这个链表的倒数第 3 个节点是值为 4 的节点。
示例:
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
题解
法一:顺序查找
思路:求出链表长度 n,顺序查找 n - k个节点即为答案
/**
* 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) {
int n = 0;
ListNode* ans = nullptr;
//求链表长度
for(ListNode* node = head; node; node = node->next){
++n;
}
//顺序查找 n - k个节点
for (ans = head; n > k; --n){
ans = ans->next;
}
return ans;
}
};
法二:DFS
参考官方题解评论区下方天赐细莲
/**
* 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) {
this->k = k;
//当类成员函数中定义了同一参数与成员变量名相同时,如this->n = n
//通过this使用类中定义的变量,来访问该成员变量
dfs(head);
return ans;
}
private:
int k;
int cnt;
ListNode* ans;
void dfs(ListNode* head){
if (head->next){
dfs(head->next);
}
++cnt;//到了尾节点,开始向上一步找,即逆序找
//逆序找到第 k 个元素,保存答案
if (k == cnt){
ans = head;
}
}
};
时间复杂度:O(n + k),n为链表长度
空间复杂度:O(n),递归调用栈的最深层数为n
法三:逆序查找
参考算法小爱
思路:通过哈希表来存储,当前节点的前一个节点。
存储完毕后,我们只需循环 k 次便可以找出答案
/**
* 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* pre = new ListNode(-1, head);
ListNode* cur = head;
unordered_map<ListNode*, ListNode*> mp;
while(cur){
cur = cur->next;
pre = pre->next;//刚进循环经过赋值操作,pre变为head
mp[cur] = pre;
}
//cur 自上一步节点变为nullptr,mp[cur]表示cur的上一个节点
while(k--){
cur = mp[cur];
}
return cur;
}
};
时间复杂度:O(n + k)
空间复杂度:O(n)
法四:快慢指针
思路:
快慢指针差k步,快的在尾巴时,慢的在倒数第k个
/**
* 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* first = head;
ListNode* second = head;
//移动快指针与慢指针差 k 个节点的
for (int i = k; i; --i){
first = first->next;
}
while(first){
first = first->next;
second = second->next;
}
return second;
}
};
以上是关于剑指 Offer 22. 链表中倒数第k个节点的主要内容,如果未能解决你的问题,请参考以下文章