数据结构与算法-剑指Offer系列(22)链表中倒数第K个节点-Java实现

42 篇文章 0 订阅
40 篇文章 0 订阅

代码的鲁棒性

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;
		
		
	}
}

考点分析:

  • 双指针,一个走得快,一个走得慢,
  • 注意代码的鲁棒性,从何时起从何时止
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值