代码的鲁棒性
Robust-程序能够判断输入是否合乎规范要求,并对不符合要求的输入予以合理的处理
容错性是鲁棒性的一个重要体现
提高鲁棒性的有效途径是进行预防性编程-指预见在什么地方会出现问题。
题目22:链表中倒数第K个节点
题目描述:
输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是值为4的结点。
解题思路:
- 为得到倒数第k个节点,很自然的想到链表的尾端,再从尾端回溯K步,可是从链表定义看出,本题链表是单向链表,单向链表的节点只有从链表节点只有从前往后的指针,没有从后往前的指针,因此行不通。
- 假设整个链表有n个节点,那么倒数k个节点就是从头结点开始的第n-k+1个节点,如果能够得到链表中节点的个数m,那么只要从头结点开始往后走n-k+1步就可以了,如何得到节点数n?从头开始遍历,每经过一个节点,计数器加一;
- 也就是遍历两次链表,第一次统计链表中节点个数,第二次就能找到倒数第k个节点,但是可能面试官希望的是遍历一次。
- 为了实现只遍历一次,定义两个指针,第一个指针从链表头指针开始向前走K-1步,第二个指针保持不动:从第k步开始,第二个指针也开始从链表的头指针开始遍历,由于两个指针的距离保持k-1,当第一个指针到达链表的尾结点时,第二个指针正好指向第k个节点。
代码实现
package swordToOffer;
import java.util.Stack;
public class Num22_KthNodeOfListNode {
public static class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
//null
ListNode head=null;
ListNode result=FindKthNode(head, 1);
if(result==null)
System.out.println("null list passed!");
else
System.out.println("null list failed!");
//超出范围
ListNode head2=new ListNode(2);
result=FindKthNode(head2, 2);
if(result==null)
System.out.println("out of range passed!");
else
System.out.println("out of range failed!");
//单个
ListNode head3=new ListNode(1);
result=FindKthNode(head3, 1);
if(result.val==1)
System.out.println("single node passed!");
else
System.out.println("signle node failed!");
//尾结点
ListNode node1=new ListNode(1);
ListNode node2=new ListNode(2);
ListNode node3=new ListNode(3);
ListNode node4=new ListNode(4);
node1.next=node2;
node2.next=node3;
node3.next=node4;
result=FindKthNode(node1, 1);
if(result.val==4)
System.out.println("last node passed!");
else
System.out.println("last node failed!");
}
//类似深度遍历 使用stack实现
public static ListNode FindKthNode(ListNode node,int k) {
if(node == null||k<=0)
return null;
int numOfList = 1;
Stack<ListNode> nodeStack = new Stack<>();
nodeStack.push(node);
ListNode next = node.next;
while(next!=null) {
nodeStack.push(next);
numOfList++;
next = next.next;
}
if(k>numOfList) {
return null;
}else {
for(int i=1;i<=k;i++) {
next = nodeStack.pop();
}
return next;
}
}
//使用双指针实现
public static ListNode FindKthNode2(ListNode node,int k) {
if(node==null|k<=0)
return null;
ListNode FHead = node;
for(int i=1;i<k;i++) {
FHead = FHead.next;
if(FHead==null)
return null;
}
ListNode SHead = node;
while(FHead.next!=null) {
FHead = FHead.next;
SHead = SHead.next;
}
return SHead;
}
}
考点分析:
- 双指针,一个走得快,一个走得慢,
- 注意代码的鲁棒性,从何时起从何时止