剑指 Offer 22.链表中倒数第k个节点
贴个题目:
贴个示例:
解题思路:
思路一:使用指针数组储存
既然题目要求倒序输出某一个节点,那我们可以用一个指针数组储存所有的指针,然后从尾部返回第k个即可。
思路一代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* getKthFromEnd(struct ListNode* head, int k){
struct ListNode* array[1000];//指针数组
int len=0;//指针数组的长度,一边储存,一边遍历
while(head!=NULL)
{
array[len++]=head;
head=head->next;
}
return array[len-k];//返回数组尾部的第k个
}
思路一性能分析:
时间分析:
一次遍历,因此时间复杂度是:O(n),n为节点个数
空间分析:
新建了一个指针数组,因此空间复杂度是:O(n)
思路二:两次遍历,一次统计长度,一次返回len-k
我们可以先新建一个节点指向head,然后一次遍历统计出有多少个节点,最后再一次遍历到len-k处的节点
思路二代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* getKthFromEnd(struct ListNode* head, int k){
struct ListNode* node =head;//新建一个节点指向head
int len=0;
//统计节点数量
while(node!=NULL)
{
len++;
node=node->next;
}
//遍历到len-k处
for(int i=0;i<len-k;i++)
head=head->next;
return head;
}
性能分析:
时间分析:
两次遍历,但是不是嵌套循环,因此时间复杂度还是:O(n)
空间分析:
新建了常数个变量,因此空间复杂度是:O(1)
思路三:快慢指针
我们可以让一个指针先前进k步,然后快慢指针同时移动,让快指针遍历到最后一个节点处,慢节点就是我们要返回的节点
贴个代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* getKthFromEnd(struct ListNode* head, int k){
struct ListNode* node =head;//快指针
while(k--)
node=node->next;//快指针前进k步
//快慢指针同时移动
while(node)
{
node=node->next;
head=head->next;
}
//返回慢指针
return head;
}
性能分析:
时间分析:
两次遍历,同样地没有发生嵌套遍历,因此时间复杂度是:O(n)
空间分析:
新建了常数个变量,因此空间复杂度是:O(1)