【剑指offer】6.链表中倒数最后k个结点

总目录:

算法之旅导航目录

 

1.问题描述

输入一个长度为 n 的链表,设链表中的元素的值为 ai ,返回该链表中倒数第k个节点。
如果该链表长度小于k,请返回一个长度为 0 的链表。
数据范围:0n10^5,0≤ai≤10^90≤k≤10^9
要求:空间复杂度 O(n),时间复杂度 O(n)
进阶:空间复杂度 O(1),时间复杂度 O(n)
例如输入{1,2,3,4,5},2时,对应的链表结构如下图所示:
其中蓝色部分为该链表的最后2个结点,所以返回倒数第2个结点(也即结点值为4的结点)即可,系统会打印后面所有的节点来比较。
 



2.问题分析
可采取的方法:
1快慢指针法,使两个指针拉开固定的长度;
2压栈弹栈法,先全部压栈,检查总数量后再取出第指定数量个元素;

3利用vector的有序属性,不必弹栈,直接索引访问更快;

3.代码实例

快慢指针法

 1 /**
 2  * struct ListNode {
 3  *    int val;
 4  *    struct ListNode *next;
 5  *    ListNode(int x) : val(x), next(nullptr) {}
 6  * };
 7  */
 8 class Solution {
 9 public:
10     /**
11      * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
12      *
13      * 
14      * @param pHead ListNode类 
15      * @param k int整型 
16      * @return ListNode类
17      */
18     ListNode* FindKthToTail(ListNode* pHead, int k) {
19         ListNode* pTgt = pHead;
20         int dis = 0;
21 
22         while (pHead != NULL) {
23             //向前推进
24             pHead = pHead->next;
25 
26             //是否已拉开足够距离
27             if (dis < k) {
28                 dis++;
29             } else {
30                 pTgt = pTgt->next;
31             }            
32         }
33 
34         //拉开的距离是否满足要求
35         return dis == k ? pTgt : NULL;
36     }
37 };
View Code

压栈弹栈法

 1 /**
 2  * struct ListNode {
 3  *  int val;
 4  *  struct ListNode *next;
 5  *  ListNode(int x) : val(x), next(nullptr) {}
 6  * };
 7  */
 8 class Solution {
 9   public:
10     /**
11      * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
12      *
13      *
14      * @param pHead ListNode类
15      * @param k int整型
16      * @return ListNode类
17      */
18     ListNode* FindKthToTail(ListNode* pHead, int k) {
19         if (pHead == NULL || k == 0) {
20             return NULL;
21         }
22 
23         stack<ListNode*> sp;
24         //全部压栈
25         while (pHead != NULL) {
26             sp.push(pHead);
27             pHead = pHead->next;
28         }
29 
30         //数量是否足够
31         if (sp.size() < k) {
32             return NULL;
33         }
34         
35         //取出倒数第k个
36         ListNode* ret = NULL;
37         while (true) {
38             if (--k == 0) {
39                 ret = sp.top();
40                 break;
41             }
42             sp.pop();
43         }
44 
45         return ret;
46     }
47 };
View Code

vector有序索引

 1 /**
 2  * struct ListNode {
 3  *    int val;
 4  *    struct ListNode *next;
 5  *    ListNode(int x) : val(x), next(nullptr) {}
 6  * };
 7  */
 8 class Solution {
 9 public:
10     /**
11      * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
12      *
13      * 
14      * @param pHead ListNode类 
15      * @param k int整型 
16      * @return ListNode类
17      */
18     ListNode* FindKthToTail(ListNode* pHead, int k) {
19         ListNode* res=nullptr;
20         vector<ListNode*> insertNode;
21         while(pHead){
22             insertNode.push_back(pHead);
23             pHead=pHead->next;
24         }
25         if(insertNode.size()<k) return res;
26         return insertNode[insertNode.size()-k];
27     }
28 };
View Code

 

posted @ 2022-11-09 22:10  啊原来是这样呀  阅读(23)  评论(0编辑  收藏  举报