题目:
输入一个链表,输出该链表中倒数第k个节点
例如,一个链表有6个节点,从头节点开始,它们的值依
次是 1、2、3、4、5、6。这个链表的倒数第3个节点是值
为4的节点。
为了实现只遍历链表一次就能找到倒数第k个节点,我们
可以定义两个指针。第一个指针从链表的头指针开始遍历
向前走k-l步,第二个指针保持不动;从第k步开始,第二
个指针也开始从链表的头指针开始遍历。 由于两个指针
的距离保持在k-l,当第一个(走在前面的)指针到达链表
的尾节点时,第二个(走在后面的)指针正好指向倒数第k
个节点。
面试官可以找出2种办法让这段代码崩溃。
• (1)输入的head为空指。由于代码会试图访问空指针指 向
的内存,从而造成程序崩溃。
• (2)输入的以head为头节点的链表的节点总数少于k。由于
在for循环中会在链表上向前走k-1步,仍然会由于空指针
而造成程序崩溃。
public static ListNode findKthToTail2(ListNode head,int k){
if(head==null||k<0){
return null;
}// 0 1 2 3 4 5 6 7 3
ListNode preNode=head;
for(int i=1;i<k;i++){
preNode=preNode.next;
if (preNode==null){
return preNode;
}
}
ListNode curNode=head;
while(preNode.next!=null){
preNode=preNode.next;
curNode=curNode.next;
}
return curNode;
}
还有一种方法就是先遍历链表的值然后把所有的值都压入栈中,最后弹出第k个
这个也要考虑长度和链表为空的情况
public static ListNode findKthToTail(ListNode head,int k) {
if (head == null || k < 0) {
return null;
}// 0 1 2 3 4 5 6 7 3
Stack<ListNode> stack=new Stack<>();
stack.push(head);
ListNode tem=head;
int len=1;
while (tem.next!=null){
tem=tem.next;
stack.push(tem);
len++;
}
if(len<k){
return null;
}
for(int i=0;i<k;i++){
tem=stack.pop();
}
return tem;
}
最后贴一下完整代码
package com.helan.c;
import java.util.Stack;
public class KthNode {
public static class ListNode{
int val;
ListNode next=null;
public ListNode(int val) {
this.val = val;
}
}
public static ListNode findKthToTail(ListNode head,int k) {
if (head == null || k < 0) {
return null;
}// 0 1 2 3 4 5 6 7 3
Stack<ListNode> stack=new Stack<>();
stack.push(head);
ListNode tem=head;
int len=1;
while (tem.next!=null){
tem=tem.next;
stack.push(tem);
len++;
}
if(len<k){
return null;
}
for(int i=0;i<k;i++){
tem=stack.pop();
}
return tem;
}
public static ListNode findKthToTail2(ListNode head,int k){
if(head==null||k<0){
return null;
}// 0 1 2 3 4 5 6 7 3
ListNode preNode=head;
for(int i=1;i<k;i++){
preNode=preNode.next;
if (preNode==null){
return preNode;
}
}
ListNode curNode=head;
while(preNode.next!=null){
preNode=preNode.next;
curNode=curNode.next;
}
return curNode;
}
void test1() {
ListNode head=null;
ListNode result=findKthToTail(head, 1);
if(result==null)
System.out.println("test1 passed!");
else
System.out.println("test1 failed!");
}
/*
* k超出范围
*/
void test2() {
ListNode head=new ListNode(2);
ListNode result=findKthToTail(head, 2);
if(result==null)
System.out.println("test2 passed!");
else
System.out.println("test2 failed!");
}
/*
* 单个结点
*/
void test3() {
ListNode head=new ListNode(1);
ListNode result=findKthToTail(head, 1);
if(result.val==1)
System.out.println("test3 passed!");
else
System.out.println("test3 failed!");
}
/*
* 尾结点
*/
void test4() {
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;
ListNode result=findKthToTail(node1, 1); //从尾部找 第1个节点 就是4
if(result.val==4)
System.out.println("test4 passed!");
else
System.out.println("test4 failed!");
}
/*
* 中间结点
*/
void test5() {
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;
ListNode result=findKthToTail(node1, 2);从尾部找 第2个节点 就是3
if(result.val==3)
System.out.println("test5 passed!");
else
System.out.println("test5 failed!");
}
/*
* 头结点
*/
void test6() {
ListNode node1=new ListNode(1);//4
ListNode node2=new ListNode(2);//3
ListNode node3=new ListNode(3);//2
ListNode node4=new ListNode(4);//1
node1.next=node2;
node2.next=node3;
node3.next=node4;
ListNode result=findKthToTail(node1, 4);从尾部找 第4个节点 就是1
if(result.val==1)
System.out.println("test6 passed!");
else
System.out.println("test6 failed!");
}
public static void main(String[] args) {
KthNode demo = new KthNode();
demo.test1();
demo.test2();
demo.test3();
demo.test4();
demo.test5();
demo.test6();
}
}