22 链表中倒数第k个节点(第3章 高质量的代码-代码的鲁棒性)
Posted GuoXinxin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了22 链表中倒数第k个节点(第3章 高质量的代码-代码的鲁棒性)相关的知识,希望对你有一定的参考价值。
题目描述:
输入一个链表,输出该链表中倒数第k个结点。
尾节点是倒数第一个节点
测试用例:
功能测试(第k个节点在中间、是头节点、是尾节点)
特殊输入测试(链表头节点是nullptr指针、链表的头节点个数小于k、k=0)
解题思路:
1)使用两个指针,一个指针先移动k步,如果链表小于k,终止返回nullptr。然后两个指针同时移动,知道后一个指针移出最后一个节点
//实现1
/* 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; //不要忘记k<0的情况 无符号不用判断k<0时; ListNode* back = pListHead; //先将指针back移动到第k个元素的位置,索引k的位置 while(back!=nullptr && k>0){ //先判断k=0,然后才是k--。 back=back->next; k--; } if(k>0) //说明链表的长度<k return nullptr; ListNode* front = pListHead; while(back!=nullptr){ //back->next!=nullptr 是错误的。 back=back->next; front=front->next; } return front; } };
注:尾节点是倒数第一个节点,因此k=1时,front应该指向尾节点,此时back应该是刚好移出尾节点,为空nullptr。
使用两个指针,一个指针先移动k-1步,如果链表小于k,终止返回nullptr。然后两个指针同时移动,知道后一个指针移动到最后一个节点
//实现1 /* 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; //无符号,所以不用判断k<0; ListNode* back = pListHead; //先将指针back移动到第k-1个元素的位置, while(back->next!=nullptr && k-1>0){ //为了得知第k个元素是否存在,应该判断back->next!=nullptr而不是back!=nullptr back=back->next; k--; } if(k>1) //说明链表的长度<k return nullptr; ListNode* front = pListHead; while(back->next!=nullptr){ //back移动到最后一个元素即可 back=back->next; front=front->next; } return front; } };
//实现2 class Solution { public: ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) { if(pListHead==nullptr || k==0)return nullptr; //无符号,所以不用判断k<0; ListNode* back = pListHead; //先将指针back移动到第k-1个元素的位置, /*while(back->next!=nullptr && k-1>0){ //为了得知第k个元素是否存在,应该判断back->next!=nullptr而不是back!=nullptr back=back->next; k--; } if(k>1) //说明链表的长度<k return nullptr;*/ for(unsigned int i=0;i<k-1;++i){ if(back->next!=nullptr) back=back->next; else return nullptr; } ListNode* front = pListHead; while(back->next!=nullptr){ //back移动到最后一个元素即可 back=back->next; front=front->next; } return front; } };
对于unsigned int类型要格外注意,在写循环或者判断时,常会遇到对变量--;这种情况要格外注意:
因为当unsigned int k=0; --k后,变量的值并不是-1,而是无符号的0xFFFFFFFF,如果此时判断k>0,还是会成立
//该方法是错误的,当k=0是,K-1为0xFFFFFFFF,back会一直向后访问超出数组 class Solution { public: ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) { if(pListHead==nullptr || k<0)return nullptr; ListNode* back = pListHead; //先将指针back移动到第k-1个元素的位置 for(unsigned int i=0; i<k-1; ++i){ bask=back->next; } if(k>1) //说明链表的长度<k return nullptr; ListNode* front = pListHead; //back移动到最后一个元素 while(back->next!=nullptr){ //back->next!=nullptr back=back->next; front=front->next; } return front; } };
相似题目:
求链表的中间节点:如果链表中的节点总数为奇数,则返回中间节点;如果链表总数是偶数,则返回中间两个节点的任意一个。
为了解决这个问题,也可以同时定义两个指针,同时从链表出发,一个指针一次走一步,另一个指针一次走两步。当走的快的指针走到链表末尾时,走的慢的指针正好在链表的中间。
以上是关于22 链表中倒数第k个节点(第3章 高质量的代码-代码的鲁棒性)的主要内容,如果未能解决你的问题,请参考以下文章