• 《剑指offer》第二十二题:链表中倒数第k个结点


    // 面试题22:链表中倒数第k个结点
    // 题目:输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,
    // 本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,
    // 从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是
    // 值为4的结点。
    
    #include <cstdio>
    #include "List.h"
    
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
    {
        //鲁棒性测试 1.空链表 2.k为0(无意义)
        if (pListHead == nullptr || k == 0)
            return nullptr;
    
        ListNode* pListAhead = pListHead;
        ListNode* pListAfter = pListHead;
        //前面的指针先走 k-1步
        for (int i = 0; i < k - 1; ++i)
        {
            if (pListAhead->m_pNext != nullptr)
                pListAhead = pListAhead->m_pNext;
            else
                return nullptr;
        }
        //然后后面指针跟上
        while (pListAhead->m_pNext != nullptr)
        {
            pListAhead = pListAhead->m_pNext;
            pListAfter = pListAfter->m_pNext;
        }
        return pListAfter;
    }
    // ====================测试代码====================
    // 测试要找的结点在链表中间
    void Test1()
    {
        printf("=====Test1 starts:=====
    ");
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(4);
        ListNode* pNode5 = CreateListNode(5);
    
        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
    
        printf("expected result: 4.
    ");
        ListNode* pNode = FindKthToTail(pNode1, 2);
        PrintListNode(pNode);
    
        DestroyList(pNode1);
    }
    
    // 测试要找的结点是链表的尾结点
    void Test2()
    {
        printf("=====Test2 starts:=====
    ");
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(4);
        ListNode* pNode5 = CreateListNode(5);
    
        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
    
        printf("expected result: 5.
    ");
        ListNode* pNode = FindKthToTail(pNode1, 1);
        PrintListNode(pNode);
    
        DestroyList(pNode1);
    }
    
    // 测试要找的结点是链表的头结点
    void Test3()
    {
        printf("=====Test3 starts:=====
    ");
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(4);
        ListNode* pNode5 = CreateListNode(5);
    
        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
    
        printf("expected result: 1.
    ");
        ListNode* pNode = FindKthToTail(pNode1, 5);
        PrintListNode(pNode);
    
        DestroyList(pNode1);
    }
    
    // 测试空链表
    void Test4()
    {
        printf("=====Test4 starts:=====
    ");
        printf("expected result: nullptr.
    ");
        ListNode* pNode = FindKthToTail(nullptr, 100);
        PrintListNode(pNode);
    }
    
    // 测试输入的第二个参数大于链表的结点总数
    void Test5()
    {
        printf("=====Test5 starts:=====
    ");
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(4);
        ListNode* pNode5 = CreateListNode(5);
    
        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
    
        printf("expected result: nullptr.
    ");
        ListNode* pNode = FindKthToTail(pNode1, 6);
        PrintListNode(pNode);
    
        DestroyList(pNode1);
    }
    
    // 测试输入的第二个参数为0
    void Test6()
    {
        printf("=====Test6 starts:=====
    ");
        ListNode* pNode1 = CreateListNode(1);
        ListNode* pNode2 = CreateListNode(2);
        ListNode* pNode3 = CreateListNode(3);
        ListNode* pNode4 = CreateListNode(4);
        ListNode* pNode5 = CreateListNode(5);
    
        ConnectListNodes(pNode1, pNode2);
        ConnectListNodes(pNode2, pNode3);
        ConnectListNodes(pNode3, pNode4);
        ConnectListNodes(pNode4, pNode5);
    
        printf("expected result: nullptr.
    ");
        ListNode* pNode = FindKthToTail(pNode1, 0);
        PrintListNode(pNode);
    
        DestroyList(pNode1);
    }
    
    int main(int argc, char* argv[])
    {
        Test1();
        Test2();
        Test3();
        Test4();
        Test5();
        Test6();
    
        return 0;
    }
    测试代码

    分析:两个指针将遍历次数减少为一次。

    /*
    struct ListNode {
        int val;
        struct ListNode *next;
        ListNode(int x) :
                val(x), next(NULL) {
        }
    };*/
    class Solution {
    public:
        ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        
            if (pListHead == nullptr || k == 0)
                return nullptr;
            
            ListNode* pListAhead = pListHead;
            ListNode* pListAfter = pListHead;
            
            for (int i = 0; i < k-1; ++i)
            {
                if (pListAhead->next != nullptr)
                    pListAhead = pListAhead->next;
                else
                    return nullptr;
            }
            
            while (pListAhead->next != nullptr)
            {
                pListAhead = pListAhead->next;
                pListAfter = pListAfter->next;
            }
            return pListAfter;
        }
    };
    牛客网提交代码

     

  • 相关阅读:
    Java异常
    JS多个对象添加到一个对象中
    JSON.parse(),JSON.stringify(),jQuery.parseJSON()
    java中什么是序列化和反序列化
    html颜色字体字符代码
    冒泡排序应用
    HTML 速查列表
    html初学(一)
    html初学(二)
    一次、二次、三次指数平滑计算思想及代码
  • 原文地址:https://www.cnblogs.com/ZSY-blog/p/12571830.html
Copyright © 2020-2023  润新知