输出单向链表中倒数第k个结点
描述
输入一个单向链表,输出该链表中倒数第k个结点,链表的倒数第1个结点为链表的尾指针。
链表结点定义如下:
struct ListNode { int m_nKey; ListNode* m_pNext; };
正常返回倒数第k个结点指针,异常返回空指针。
示例:
输入:
8
1 2 3 4 5 6 7 8
4
1 2 3 4 5 6 7 8
4
输出:5
方法一
思路分析
本题最直接的办法就是根据输入的数组直接输出倒数第k个数,不过本题题目要求使用单向链表,因此直接构造单向链表,然后顺序输出倒数第k个结点,输出时采用输出第n-k个结点。
核心代码
#include <bits/stdc++.h> using namespace std; struct Node{ int value; struct Node* next; Node(int value) { this->value=value; } }; int main(){ int count=0; while(cin>>count) { Node *root = new Node(-1); Node *p = root; for (int i=0; i < count; ++i)//顺序构造链表 { int num; cin>>num; Node *p = new Node(num);//下一个结点 p->next = NULL; root->next = p;// 连接 当前节点 与 下一个结点 root = root->next; } root->next = NULL;//最后一个节点指向mull int k=0; cin>>k; if(k<=0||k>count) { cout<<0<<endl; continue; } for(int i=0;i<count-k+1;i++)//顺序找到第count-k个 { p=p->next; } cout<<p->value<<endl; } }复杂度分析
- 时间复杂度:时间花费在链表的构造和查找中,构造链表的时间复杂度为$O(n)$,查找的时间复杂度为$O(n)$,因此总的时间复杂度为$O(n)$
- 空间复杂度:构造链表需要的空间为正常使用,因此总的空间复杂度为$O(1)$
方法二
思路分析
根据方法一,我们可以设置一个数组存储输入的元素,然后根据数组元素从后往前构造链表,从而顺序输出链表第k个结点
核心代码
#include <bits/stdc++.h> using namespace std; struct Node{ int value; struct Node* next; Node(int value) { this->value=value; } }; vector<int>arr; int main(){ int count=0; while(cin>>count) { int index=count; arr={}; while(index--) { int num; cin>>num; arr.push_back(num); } Node *root = new Node(-1); Node *p = root; for (int i=count-1;i>=0; i--)//按照数组倒序构造链表 { Node *p = new Node(arr[i]);//下一个结点 p->next = NULL; root->next = p;// 连接 当前节点 与 下一个结点 root = root->next; } root->next = NULL;//最后一个节点指向mull int k=0; cin>>k; if(k<=0||k>count) { cout<<0<<endl; continue; } for(int i=0;i<k;i++)//顺序找到第k个 { p=p->next; } cout<<p->value<<endl; } }
复杂度分析
- 时间复杂度:时间花费在链表的构造和查找中,构造链表的时间复杂度为$O(n)$,查找的时间复杂度为$O(n)$,因此总的时间复杂度为$O(n)$
- 空间复杂度:需要额外设置一个数组存储输入的元素,因此总的空间复杂度为$O(max(n))$
方法三
思路分析
在构建链表时,可以通过首插法构造链表,然后顺序输出第k个结点
图解
核心代码
#include <bits/stdc++.h> using namespace std; struct Node{ int value; struct Node* next; Node(int value) { this->value=value; } }; vector<int>arr; int main(){ int count=0; while(cin>>count) { Node *root = new Node(-1); root->next=NULL; for (int i=0;i<count; i++)//按照首插法构造链表 { int num=0; cin>>num; Node *p = new Node(num);//下一个结点 p->next = root;//插入到根节点之前 root= p;// 根节点向前移动一个位置 } int k=0; cin>>k; if(k<=0||k>count) { cout<<0<<endl; continue; } for(int i=0;i<k-1;i++)//从前往后顺序找到第k个 { root=root->next; } cout<<root->value<<endl; } }复杂度分析
- 时间复杂度:时间花费在链表的构造和查找中,构造链表的时间复杂度为$O(n)$,查找的时间复杂度为$O(n)$,因此总的时间复杂度为$O(nm)$
- 空间复杂度:除构造链表之外,不需要额外的存储空间,因此空间复杂度为$O(1)$