[程序员面试题精选100题]9.链表中倒数第k个结点

简介:

题目

输入一个单向链表,输出该链表中倒数第k个结点。链表的倒数第0个结点为链表的尾指针。

思路一

因为是单向链表,只有从前往后的指针而没有从后往前的指针。因此我们不能倒序遍历链表,只能正序遍历。假设整个链表有n个结点,那么倒数第k个结点是从头结点开始的第n-k-1个结点(从0开始计数)。我们只需要得到链表中结点的个数n,那我们只要从头结点开始往后走n-k-1步就可以了。
因此这种方法需要遍历链表两次。第一次得到链表中结点个数n,第二次得到从头结点开始的第n-k-1个结点即倒数第k个结点。时间复杂度为O(n)。

代码

    /*------------------------------------
    *   日期:2015-02-08
    *   作者:SJF0115
    *   题目: 9.链表中倒数第k个结点
    *   来源:程序员面试题精选100题
    ---------------------------------------*/
    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <queue>
    using namespace std;

    struct ListNode{
        int val;
        ListNode *next;
        ListNode(int x):val(x),next(NULL){}
    };

    class Solution {
    public:
        ListNode* FindKthTailNode(ListNode* head,int k) {
            if(head == nullptr || k < 0){
                return nullptr;
            }//if
            // 统计链表个数
            int count = 0;
            ListNode *p = head;
            while(p){
                p = p->next;
                ++count;
            }//while
            // 不足K个
            if(count < k){
                return nullptr;
            }//if
            // 倒数第K个节点
            int pos = count - k;
            p = head;
            for(int i = 0;i < pos;++i){
                p = p->next;
            }//for
            return p;
        }
    };

    int main(){
        Solution s;
        ListNode *head = new ListNode(1);
        ListNode *node;
        for(int i = 8;i >= 2;--i){
            node = new ListNode(i);
            node->next = head->next;
            head->next = node;
        }//for

        ListNode *result = s.FindKthTailNode(head,3);

        // 输出
        if(result == nullptr){
            cout<<"nullptr"<<endl;
        }//if
        else{
            cout<<result->val<<endl;
        }//else
        return 0;
    }

思路二

上面那种思路需要两次遍历,如何才能只需一次遍历呢?
如果我们在遍历时维持两个指针,第一个指针从链表的头指针开始遍历,在第k-1步之前,第二个指针保持不动, k-1 步开始,第二个指针也开始从链表的头指针开始遍历,两个指针齐头并进。由于两个指针的距离保持在k-1;当第一个(走在前面的)指针到达链表的尾结点时,第二个指针(走在后面的)指针正好是倒数第
K个节点。

代码二

    /*------------------------------------
    *   日期:2015-02-08
    *   作者:SJF0115
    *   题目: 9.链表中倒数第k个结点
    *   来源:程序员面试题精选100题
    ---------------------------------------*/
    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <queue>
    using namespace std;

    struct ListNode{
        int val;
        ListNode *next;
        ListNode(int x):val(x),next(NULL){}
    };

    class Solution {
    public:
        ListNode* FindKthTailNode(ListNode* head,int k) {
            if(head == nullptr || k < 0){
                return nullptr;
            }//if
            ListNode *p = head,*q = head;
            // 指针p移动k-1步
            int index = 1;
            while(index < k && p != nullptr){
                p = p->next;
                ++index;
            }//while
            // 不够K个
            if(p == nullptr){
                return nullptr;
            }//if
            // 同时移动
            while(p->next){
                p = p->next;
                q = q->next;
            }//while
            return q;
        }
    };

    int main(){
        Solution s;
        ListNode *head = new ListNode(1);
        ListNode *node;
        for(int i = 8;i >= 2;--i){
            node = new ListNode(i);
            node->next = head->next;
            head->next = node;
        }//for

        ListNode *result = s.FindKthTailNode(head,8);

        // 输出
        if(result == nullptr){
            cout<<"nullptr"<<endl;
        }//if
        else{
            cout<<result->val<<endl;
        }//else
        return 0;
    }

拓展

输入一个单向链表。如果该链表的结点数为奇数,输出中间的结点;如果链表结点数为偶数,输出中间两个结点前面的一个节点。

代码

    /*------------------------------------
    *   日期:2015-02-08
    *   作者:SJF0115
    *   题目: 9.2链表中间结点
    *   来源:程序员面试题精选100题
    ---------------------------------------*/
    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <queue>
    using namespace std;

    struct ListNode{
        int val;
        ListNode *next;
        ListNode(int x):val(x),next(NULL){}
    };

    class Solution {
    public:
        ListNode* FindMidNode(ListNode* head) {
            if(head == nullptr){
                return nullptr;
            }//if
            ListNode *slow = head,*fast = head;
            while(fast->next != nullptr && fast->next->next != nullptr){
                slow = slow->next;
                fast = fast->next->next;
            }//while
            return slow;
        }
    };

    int main(){
        Solution s;
        ListNode *head = new ListNode(1);
        ListNode *node;
        for(int i = 8;i >= 2;--i){
            node = new ListNode(i);
            node->next = head->next;
            head->next = node;
        }//for

        ListNode *result = s.FindMidNode(head);

        // 输出
        if(result == nullptr){
            cout<<"nullptr"<<endl;
        }//if
        else{
            cout<<result->val<<endl;
        }//else
        return 0;
    }
目录
相关文章
|
1月前
|
机器学习/深度学习 算法
24. 两两交换链表中的节点, 19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交
1. **两两交换链表中的节点**:通过引入虚拟头结点,使所有节点都能采用统一的交换逻辑,避免对头结点单独处理。 2. **删除链表的倒数第N个节点**:利用双指针技巧,让快慢指针保持N个节点的距离,当快指针到达末尾时,慢指针正好指向待删除节点的前一个节点。 3. **链表相交**:先计算两链表长度并调整起点,确保从相同距离末尾的位置开始遍历,从而高效找到相交节点或确定无交点。 以上方法均在时间复杂度和空间复杂度上进行了优化,适合用于理解和掌握链表的基本操作及常见算法设计思路。
|
9月前
|
算法
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
144 1
|
10月前
链表的中间结点
链表的中间结点
285 57
|
8月前
|
存储 算法 搜索推荐
链表的中间结点
【10月更文挑战第24天】链表的中间结点是链表操作中的一个重要概念,通过快慢指针法等方法可以高效地找到它。中间结点在数据分割、平衡检测、算法应用等方面都有着重要的意义。在实际编程中,理解和掌握寻找中间结点的方法对于解决链表相关问题具有重要价值。
77 1
|
9月前
|
存储 算法 安全
HashMap常见面试题(超全面):实现原理、扩容机制、链表何时升级为红黑树、死循环
HashMap常见面试题:红黑树、散列表,HashMap实现原理、扩容机制,HashMap的jd1.7与jdk1.8有什么区别,寻址算法、链表何时升级为红黑树、死循环
|
9月前
【LeetCode 09】19 删除链表的倒数第 N 个结点
【LeetCode 09】19 删除链表的倒数第 N 个结点
57 0
|
存储 SQL 算法
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
|
存储 SQL 算法
LeetCode 题目 86:分隔链表
LeetCode 题目 86:分隔链表
|
存储 算法 Java
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
110 2
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点.
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点
145 1