图解算法——链表中倒数第k个节点

题目来源:

剑指 Offer 22. 链表中倒数第k个节点

leetCode

题目描述:

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。

示例:

给定一个链表: 1->2->3->4->5, 和 k = 2.

返回链表 4->5.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

解题思路:

拿到该题目,第一想法是:

  1. 先遍历统计链表长度,记为 n;
  2. 设置一个指针走 (n-k) 步,即可找到链表倒数第 k个节点。

执行完毕后发现,情况惨不忍睹。时间4ms,内存10.9MB,才击败10.34%的对手。白瞎了我这专业真是。不过冷静下来想一想,也是,这笨办法只要是受过“高等教育”的谁不会?我表弟(高中)说他也会。鄙视........

图解算法——链表中倒数第k个节点

 

 

冷静下来,想一想,确实没有必要进行二次循环。 太浪费时间了。那么如何能在一次循环中就能够找到倒数第k个节点呢???

淦,如果有一把尺子,刚好长度为k,那么在尺子前端顶到链表尾部后,那尺子尾端必然是处于链表的倒数第k个节点处啊,卧槽,那怎么办?

尺子的问题,滑动窗口的问题,卧槽,思路来了,双指针!!!对滴,没错,就是他!

流程:

1、初始化两个指针:latter和former,都指向head;

2、构造出长度为k的尺子:先让former先走k步;

3、一起走:等former走到链表尽头,latter就所在位置就是倒数第k所在位置。

以链表 1->2->3->4->5, 和 k = 2 为例:

图解算法——链表中倒数第k个节点

初始化双指针:latter = head; former = head;

然后former走第一步:

图解算法——链表中倒数第k个节点

 

 走第二步:

图解算法——链表中倒数第k个节点

 

至此,长度为k 的 尺子构建完毕。

双指针开始同步移动:

走一步

图解算法——链表中倒数第k个节点

 

 再走一步:

图解算法——链表中倒数第k个节点

 

 再走一步:

图解算法——链表中倒数第k个节点

 

 发现没?此时former已经指向NULL了,跳出循环。

由于题目上说倒数第k个要符合习惯。

故,此时latter所指向的节点即是倒数第k个节点,此处k=2。

有些题目上就没有说习惯的问题,所以former指针到底先走几步,到哪停,要也别注意,也要灵活运用。

图解算法——链表中倒数第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* former = head;
        ListNode* latter = head;
        int n = 1;
       if(head==NULL)
            return NULL;
        while(k--){
            former = former->next;
        }
        while(former!=NULL)
        {
            latter = latter->next;
            former = former->next;
        }
        return latter ;
    }
};

 

 

Over......

 

上一篇:leveldb源码分析之写sst文件


下一篇:算法攻关 - 链表中倒数第K个节点(O(n))_22