当前位置: 代码迷 >> 综合 >> 02.02 返回倒数第k个节点
  详细解决方案

02.02 返回倒数第k个节点

热度:98   发布时间:2024-03-10 01:07:49.0

原题目

面试题 02.02. 返回倒数第 k 个节点

实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。

**注意:**本题相对原题稍作改动

示例:

输入: 1->2->3->4->5 和 k = 2
输出: 4

说明:

给定的 k 保证是有效的。


第一遍解法

头插法会使链表倒序,先使用头插法创建一个新链表,然后返回第k个节点的值即可。

/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
    
public:int kthToLast(ListNode* head, int k) {
    ListNode *pre = new ListNode(0);while (head != NULL) {
    ListNode *cur = new ListNode(head->val);cur->next = pre->next;pre->next = cur;head = head->next;}while (k--) {
    pre = pre->next;}return pre->val;}
};

时间复杂度: O(n)

空间复杂度: O(n)


网上好的解法

双指针,第一个指针指向head,第二个指针指向第k个位置的元素,那么第二个指针到链尾的距离为length - k。所以可以同步右移两个指针,当第二个指针指向最后一个元素时,第一个指针就指向倒数第k个元素。 妙啊!

class Solution {
    
public:int kthToLast(ListNode* head, int k) {
    if(head == NULL)            //常规判断return 0;ListNode *pre = head;       //前指针ListNode *p = head;         //后指针 int i = 0;              //i用来确保后指针移动到第K个位置while(i < k){
    if(p == NULL)       return 0;p = p->next;i++;}while(p != NULL){
           //相距K个,同步移动,直到后指针到链表尾部。pre = pre->next;p = p->next;}return pre->val;}
};作者:jameswu
链接:https://leetcode-cn.com/problems/kth-node-from-end-of-list-lcci/solution/shuang-zhi-zhen-tong-bu-yi-dong-shuang-100tong-guo/
来源:力扣(LeetCode)

最后,简化了一下上面的代码:

class Solution {
    
public:int kthToLast(ListNode* head, int k) {
    ListNode *p = head;ListNode *q = p;while(--k) {
    q = q->next;}while(q->next != NULL) {
    p = p->next;q = q->next;}return p->val;}
};

时间复杂度: O(n)

空间复杂度: O(1)


最后的代码

我认为简化版的同步移动可能是比较好的版本。

class Solution {
    
public:int kthToLast(ListNode* head, int k) {
    ListNode *p = head;ListNode *q = p;while(--k) {
    q = q->next;}while(q->next != NULL) {
    p = p->next;q = q->next;}return p->val;}
};

时间复杂度: O(n)

空间复杂度: O(1)


小结

  • 头插法会使链表逆序。
  • 链表问题应常考虑双指针的思路。
  相关解决方案