题目
输入一个单向链表,输出该链表中倒数第k个结点。链表的倒数第0个结点为链表的尾指针。
思路一
因为是单向链表,只有从前往后的指针而没有从后往前的指针。因此我们不能倒序遍历链表,只能正序遍历。假设整个链表有n个结点,那么倒数第k个结点是从头结点开始的第n-k-1个结点(从0开始计数)。我们只需要得到链表中结点的个数n,那我们只要从头结点开始往后走n-k-1步就可以了。
因此这种方法需要遍历链表两次。第一次得到链表中结点个数n,第二次得到从头结点开始的第n-k-1个结点即倒数第k个结点。时间复杂度为O(n)。
代码
<code class=" hljs cpp" style="box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; padding: 0.5em; color: rgb(0, 0, 0); border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; display: block; background-color: transparent !important;"> <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">/*------------------------------------ * 日期:2015-02-08 * 作者:SJF0115 * 题目: 9.链表中倒数第k个结点 * 来源:程序员面试题精选100题 ---------------------------------------*/</span> <span class="hljs-preprocessor" style="box-sizing: border-box; color: rgb(136, 0, 0);">#include <iostream></span> <span class="hljs-preprocessor" style="box-sizing: border-box; color: rgb(136, 0, 0);">#include <cstring></span> <span class="hljs-preprocessor" style="box-sizing: border-box; color: rgb(136, 0, 0);">#include <vector></span> <span class="hljs-preprocessor" style="box-sizing: border-box; color: rgb(136, 0, 0);">#include <queue></span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">using</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">namespace</span> <span class="hljs-built_in" style="box-sizing: border-box; font-weight: bold;">std</span>; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">struct</span> ListNode{ <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> val; ListNode *next; ListNode(<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> x):val(x),next(NULL){} }; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">class</span> Solution { <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">public</span>: ListNode* FindKthTailNode(ListNode* head,<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> k) { <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">if</span>(head == <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">nullptr</span> || k < <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">0</span>){ <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">return</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">nullptr</span>; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//if</span> <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">// 统计链表个数</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> count = <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">0</span>; ListNode *p = head; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">while</span>(p){ p = p->next; ++count; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//while</span> <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">// 不足K个</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">if</span>(count < k){ <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">return</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">nullptr</span>; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//if</span> <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">// 倒数第K个节点</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> pos = count - k; p = head; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">for</span>(<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> i = <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">0</span>;i < pos;++i){ p = p->next; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//for</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">return</span> p; } }; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> main(){ Solution s; ListNode *head = <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">new</span> ListNode(<span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">1</span>); ListNode *node; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">for</span>(<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> i = <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">8</span>;i >= <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">2</span>;--i){ node = <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">new</span> ListNode(i); node->next = head->next; head->next = node; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//for</span> ListNode *result = s.FindKthTailNode(head,<span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">3</span>); <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">// 输出</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">if</span>(result == <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">nullptr</span>){ <span class="hljs-built_in" style="box-sizing: border-box; font-weight: bold;">cout</span><<<span class="hljs-string" style="box-sizing: border-box; color: rgb(136, 0, 0);">"nullptr"</span><<endl; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//if</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">else</span>{ <span class="hljs-built_in" style="box-sizing: border-box; font-weight: bold;">cout</span><<result->val<<endl; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//else</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">return</span> <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">0</span>; } </code>
思路二
上面那种思路需要两次遍历,如何才能只需一次遍历呢?
如果我们在遍历时维持两个指针,第一个指针从链表的头指针开始遍历,在第k-1步之前,第二个指针保持不动, k-1 步开始,第二个指针也开始从链表的头指针开始遍历,两个指针齐头并进。由于两个指针的距离保持在k-1;当第一个(走在前面的)指针到达链表的尾结点时,第二个指针(走在后面的)指针正好是倒数第
K个节点。
代码二
<code class=" hljs cpp" style="box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; padding: 0.5em; color: rgb(0, 0, 0); border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; display: block; background-color: transparent !important;"> <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">/*------------------------------------ * 日期:2015-02-08 * 作者:SJF0115 * 题目: 9.链表中倒数第k个结点 * 来源:程序员面试题精选100题 ---------------------------------------*/</span> <span class="hljs-preprocessor" style="box-sizing: border-box; color: rgb(136, 0, 0);">#include <iostream></span> <span class="hljs-preprocessor" style="box-sizing: border-box; color: rgb(136, 0, 0);">#include <cstring></span> <span class="hljs-preprocessor" style="box-sizing: border-box; color: rgb(136, 0, 0);">#include <vector></span> <span class="hljs-preprocessor" style="box-sizing: border-box; color: rgb(136, 0, 0);">#include <queue></span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">using</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">namespace</span> <span class="hljs-built_in" style="box-sizing: border-box; font-weight: bold;">std</span>; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">struct</span> ListNode{ <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> val; ListNode *next; ListNode(<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> x):val(x),next(NULL){} }; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">class</span> Solution { <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">public</span>: ListNode* FindKthTailNode(ListNode* head,<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> k) { <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">if</span>(head == <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">nullptr</span> || k < <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">0</span>){ <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">return</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">nullptr</span>; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//if</span> ListNode *p = head,*q = head; <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">// 指针p移动k-1步</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> index = <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">1</span>; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">while</span>(index < k && p != <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">nullptr</span>){ p = p->next; ++index; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//while</span> <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">// 不够K个</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">if</span>(p == <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">nullptr</span>){ <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">return</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">nullptr</span>; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//if</span> <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">// 同时移动</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">while</span>(p->next){ p = p->next; q = q->next; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//while</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">return</span> q; } }; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> main(){ Solution s; ListNode *head = <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">new</span> ListNode(<span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">1</span>); ListNode *node; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">for</span>(<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> i = <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">8</span>;i >= <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">2</span>;--i){ node = <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">new</span> ListNode(i); node->next = head->next; head->next = node; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//for</span> ListNode *result = s.FindKthTailNode(head,<span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">8</span>); <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">// 输出</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">if</span>(result == <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">nullptr</span>){ <span class="hljs-built_in" style="box-sizing: border-box; font-weight: bold;">cout</span><<<span class="hljs-string" style="box-sizing: border-box; color: rgb(136, 0, 0);">"nullptr"</span><<endl; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//if</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">else</span>{ <span class="hljs-built_in" style="box-sizing: border-box; font-weight: bold;">cout</span><<result->val<<endl; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//else</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">return</span> <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">0</span>; } </code>
拓展
输入一个单向链表。如果该链表的结点数为奇数,输出中间的结点;如果链表结点数为偶数,输出中间两个结点前面的一个节点。
代码
<code class=" hljs cpp" style="box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; padding: 0.5em; color: rgb(0, 0, 0); border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; display: block; background-color: transparent !important;"> <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">/*------------------------------------ * 日期:2015-02-08 * 作者:SJF0115 * 题目: 9.2链表中间结点 * 来源:程序员面试题精选100题 ---------------------------------------*/</span> <span class="hljs-preprocessor" style="box-sizing: border-box; color: rgb(136, 0, 0);">#include <iostream></span> <span class="hljs-preprocessor" style="box-sizing: border-box; color: rgb(136, 0, 0);">#include <cstring></span> <span class="hljs-preprocessor" style="box-sizing: border-box; color: rgb(136, 0, 0);">#include <vector></span> <span class="hljs-preprocessor" style="box-sizing: border-box; color: rgb(136, 0, 0);">#include <queue></span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">using</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">namespace</span> <span class="hljs-built_in" style="box-sizing: border-box; font-weight: bold;">std</span>; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">struct</span> ListNode{ <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> val; ListNode *next; ListNode(<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> x):val(x),next(NULL){} }; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">class</span> Solution { <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">public</span>: ListNode* FindMidNode(ListNode* head) { <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">if</span>(head == <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">nullptr</span>){ <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">return</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">nullptr</span>; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//if</span> ListNode *slow = head,*fast = head; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">while</span>(fast->next != <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">nullptr</span> && fast->next->next != <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">nullptr</span>){ slow = slow->next; fast = fast->next->next; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//while</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">return</span> slow; } }; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> main(){ Solution s; ListNode *head = <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">new</span> ListNode(<span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">1</span>); ListNode *node; <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">for</span>(<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> i = <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">8</span>;i >= <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">2</span>;--i){ node = <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">new</span> ListNode(i); node->next = head->next; head->next = node; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//for</span> ListNode *result = s.FindMidNode(head); <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">// 输出</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">if</span>(result == <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">nullptr</span>){ <span class="hljs-built_in" style="box-sizing: border-box; font-weight: bold;">cout</span><<<span class="hljs-string" style="box-sizing: border-box; color: rgb(136, 0, 0);">"nullptr"</span><<endl; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//if</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">else</span>{ <span class="hljs-built_in" style="box-sizing: border-box; font-weight: bold;">cout</span><<result->val<<endl; }<span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">//else</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">return</span> <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">0</span>; }</code>