题目:输出链表的倒数第k个节点
分析:
方法一:
先遍历链表,得到链表的总长度n,然后再次从头遍历链表定位到第(n-k+1)的节点,最后输出。这种方法需要遍历链表两次,但是鲁棒性好,对于输入的数据能较好的得到结果,但是该方法需要遍历链表两次,时间花费较多。
方法二:
设两个头指针,第一个头指针往下遍历,直到第k-1个节点的时候停止,然后两个指针同时向后遍历,当第一个指针到达链表尾部的时候,第二个指针正好指向倒数第k个节点。该方法只需要遍历链表一次,时间花费较少,但是该算法鲁棒性比方法一要稍微差一点,因为当输入的数据大于链表的长度的时候,程序是会出错的,鲁棒性较差。
方法一和方法二的代码如下:
package problem2;
/**
* @author Hutongling
*
*/
public class 输出倒数第k个节点 {
//遍历链表两次的方法
static Node getTheRevseKthNode(Node head,int k){
if(head==null)
return null;
Node head1=head;
int count=0;
int i=0;
while(head.next!=null){
++count;
head=head.next;
}
if(k<1 || k>count+1){
System.out.println("输入范围应该是" + 1 + "到" + (count+1) + "之间的整数");
return null;
}
while(i<count-k+1){
head1=head1.next;
i++;
}
System.out.println("方法1:倒数第" + k + "节点的值为:" +head1.value);
return head;
}
//只需要遍历链表一次的方法,该方法虽然可以得到正确的解,但是也存在一点问题,当输入的数大于链表的长度的时候会出现问题,故鲁棒性不如上面的方法
static Node getTheRevseKthNode1(Node head,int k){
if(head==null)
return null;
Node node1=head;
Node head2=head;
int count=0;
for(int i=1;i<k;i++){
count++;
if(node1.next!=null)
node1=node1.next;
else {
System.out.println("请输入正确的范围!");
return null;
}
}
while(node1.next!=null){
count++;
node1=node1.next;
head=head.next;
}
System.out.println("方法2:倒数第" + k + "节点的值为:" +head.value);
return head;
}
public static void main(String[] args) {
int data[]={1,2,3,4,5,6,7,8,9,10,11,12,14,14,15,27};
Node head1=new Node(data[0]); //新建链表的头结点
Node head2=head1; //保留链表的头结点
for(int i=1;i<data.length;i++){ //用尾插法创建一个链表
Node node1=new Node(data[i]);
head1.next=node1;
head1=node1;
}
getTheRevseKthNode(head2, 11);
getTheRevseKthNode1(head2, 11);
System.out.print("原数组为:");
while(head2.next !=null){
System.out.print(head2.value + " ");
head2=head2.next;
}
System.out.println(head2.value);
}
}
注:Node的定义在此处
代码结果:
方法1:倒数第11节点的值为:6
方法2:倒数第11节点的值为:6
原数组为:1 2 3 4 5 6 7 8 9 10 11 12 14 14 15 27