本文为剑指 offer 系列第十六篇。
主要知识点为链表,就是在链表遍历的基础上进行查找操作,细心一点也没啥问题。
输入一个链表,输出该链表中倒数第k个结点。
解题思路
思路1
先将链表遍历一遍,计算总的结点的个数。
然后计算倒数第k个是正数第多少个,然后再遍历一遍,找到要输出的结点。
思路2
通过双指针来解决问题。快的结点要比慢的结点提前k个,
当后面那个走到尾节点所指向的空结点的时候,慢的指针刚好指向要求输出的节点。
解题代码
思路1代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| /* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/ class Solution { public: ListNode* FindKthToTail(ListNode* phead, unsigned int k) { //方法一,先跑一遍,计算总的个数。然后计算倒数第k个是正数第多少个,然后再遍历一遍。 if(!phead || k == 0) return NULL; int count = 0; ListNode* p = phead; while(p){ p = p->next; count++; } if(count < k) return NULL; p = phead; for(int i = count-k; i>0; i--){ p = p->next; } return p; } };
|
时间复杂度为O(n),空间复杂度为O(n)
思路2代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Solution { public: ListNode* FindKthToTail(ListNode* phead, unsigned int k) { //方法二:快慢双指针。 if(!phead || k == 0) return NULL; ListNode* fast, *slow; fast = slow = phead; for(int i = 0;i<k;i++){ fast = fast->next; if(!fast && i==k-1) return phead; if(!fast) return NULL; } while(fast){ fast = fast->next; slow = slow->next; } return slow; } };
|
或者可以用另一种写法,比较优美一点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| /* 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 || k <= 0) return NULL; ListNode* fast = pListHead; ListNode* slow = pListHead; while(k>0 && fast){ k--; fast = fast->next; } while(fast){ fast = fast->next; slow = slow->next; } return k>0?NULL:slow; } };
|
时间复杂度为O(n),空间复杂度为O(n)
以上,本题结束!