【面试题15】链表中倒数第k个结点

【题目描述】

输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第一个结点。

例如,一个链表有6个结点,从头结点开始他们的值依次是1,2,3,4,5,6。

这个链表的都属第三个结点是值为4的结点。

【解决方案】

方法:设置两个指针p1,p2。p1先走k个结点,然后p2开始和p1同步走,p1走到尾结点的时候,p2所指的结点即为倒数第k个结点。

考虑特殊情况:

1. 链表为空;

2. 链表结点数量小于k;

3. 输入k小于等于0的情况,会影响程序的鲁棒性(具体看代码);

我的代码实现,仅供参考:

 1         public static ListNode FindKthNode(ListNode head, int k)
 2         {
 3             if (head == null || k<=0)
 4             {
 5                 return null;
 6             }
 7             
 8             ListNode p1 = head , p2 = head;
 9 
10             //根据题意链表尾节点为倒数第一个
11             //故i < k-1,所以k > 0
12             for (int i = 0; i < k-1; i++)
13             {
14                 //处理链表结点数量小于k的情况
15                 if (p1.Next == null)
16                 {
17                     return null;
18                 }
19                 else
20                 { 
21                     p1 = p1.Next;
22                 }
23             }
24 
25             while (p1.Next != null)
26             {
27                 p1 = p1.Next;
28                 p2 = p2.Next;
29             }
30 
31             return p2;
32         }

【相关题目】

1. 求链表的中间结点。如果链表中结点总数为奇数,则返回中间结点,如果为偶数,则返回中间结点两个中的任意一个。

方法:设置两个指针p1,p2。同时从head开始走,p1每次走两步,p2每次走一步,p1到达尾节点时,p2所指结点即为中间结点。

我的代码实现,仅供参考:

 1         public static ListNode FindMidhNode(ListNode head)
 2         {
 3             if (head == null)
 4             {
 5                 return null;
 6             }
 7 
 8             ListNode p1 = head, p2 = head;
 9 
10             while (p1.Next!=null && p1.Next.Next != null)
11             {
12                 p1 = p1.Next.Next;
13                 p2 = p2.Next;
14             }
15 
16             return p2;
17         }

2. 判断一个单向链表是否形成了环形结构。

方法:设置两个指针p1,p2。同时出发,p1每次走两步,p2每次走一步,如果p1追上p2,和p2所指结点相同,则证明链表中存在环形结构。

我的代码实现,仅供参考:

 1         public static bool HasCircle(ListNode head)
 2         {
 3             if (head == null || head.Next == null)
 4             {
 5                 return false;
 6             }
 7 
 8             ListNode p1 = head.Next, p2 = head;
 9             bool hasCircle = false;
10 
11             while (p1.Next != null && p1.Next.Next != null)
12             {
13                 if (p1 == p2)
14                 {
15                     hasCircle = true;
16                     break;
17                 }
18                 p1 = p1.Next.Next;
19                 p2 = p2.Next;
20             }
21 
22             return hasCircle;
23         }

 【举一反三】

当我们用一个指针遍历链表不能解决问题的时候,可以尝试用两个指针来遍历链表。可以让其中一个指针遍历的速度快一些,或者让它先在链表上走若干步。

原文地址:https://www.cnblogs.com/HuoAA/p/4803165.html