zoukankan      html  css  js  c++  java
  • 链表中的倒数第k个结点

    • 问题描述:

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

    struct ListNode{
    	int m_nValue;
    	ListNode* m_pNext;
    }
    
    • 分析:

       要得到倒数第k个结点,也就是正数第n-k+1(其中n为结点总数)个结点,所以又有了最简单粗暴的方法:先遍历一次链表,每遍历一个结点计数器加一,最后得到n,然后第二次遍历链表,找到第n-k+1个结点,问题解决。
       当然,面试官会希望我们只遍历一次链表就得到结果,那么我们就需要定义两个指针了。我们希望遍历结束的时候,一个指针指向末尾结点,而另一个指针指向倒数第k个结点。所以,我们用第一个指针从头遍历链表,当其指向第k个结点的时候,令第二个指针指向第一个结点,然后两个指针一起向前遍历,知道第一个指针到达链表末尾,此时第二个指针所指的结点即倒数第k个结点。代码如下:

      ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
      {
         if(pListHead == NULL || k == 0)
         	return NULL;
         
         ListNode *pAhead = pListHead;
         ListNode *pBehind = NULL;
          
         for(int i = 0; i < k-1; ++i)
         {
         	if(pAhead->m_pNext != NULL)
         		 pAhead = pAhead->m_pNext;
         	else
         		return NULL;
         }
         
         pBehind = pListHead;
         while(pAhead->m_pNext != NULL)
         {
         	pAhead = pAhead->m_pNext;
         	pBehind = pBehind->m_pNext;
         }
         return pBehind;
      }
      

      值得注意的是,我们不仅要写出代码,还要考虑代码的鲁棒性。以此题为例,我们需要考虑一下三种情况:

      • 输入的链表头指针pListHead为空指针
      • 输入的参数k为0
      • 输入的以pListHead为头结点的链表中的结点总数少于k
    • 相关题目:
      1)求链表结点的中间结点。如果链表结点的总数为奇数,则返回中间结点;如果结点总数是偶数,则返回中间两个结点中的任意一个。
      思路:依然使用两个指针,这两个指针同时从头结点开始,一个一次向后移两步,一个一次向后移一步,则当走的快的指针到达链表末尾时,走的慢的指针刚好在链表中间。
      2)判断一个单链表是否形成了环形结构。

    解题思路:对于一个链表的问题,用一个指针遍历不能解决问题时,可以尝试使用两个指针来遍历链表。并让一个指针遍历的速度快一些,或者让它先在链表上走若干步。

  • 相关阅读:
    Android源码编译jar包BUILD_JAVA_LIBRARY 与BUILD_STATIC_JAVA_LIBRARY的区别(一)
    模块化开发
    最近理解记忆
    ES6语法—— 模块化开发之import和export命令详解
    关于阿里图标库Iconfont生成图标的三种使用方式(fontclass/unicode/symbol)
    2.新知-display:inline-block元素之间空隙的产生原因和解决办法
    规避同源
    vue总结
    vue组件通信
    vue 多次学习
  • 原文地址:https://www.cnblogs.com/Bill-LHR/p/6756387.html
Copyright © 2011-2022 走看看