【牛客-剑指offer-数据结构篇】【图解】JZ22 链表中倒数最后k个结点 两种方案 Java实现


1 题目链接

https://www.nowcoder.com/exam/oj/ta?page=1&tpId=13&type=265

2 题目

在这里插入图片描述
在这里插入图片描述

3 解答

3.1 方案一(统计链表长度)

思路

  1. 统计整个链表的长度len
  2. 用len和题目所给的k进行比较,有三种情况
    • len < k
      • 这种情况是不存在的,比如:链表长度是5,返回倒数第7个节点…
    • len = k
      • 这是这道题特殊情况,比如:链表长度是5,返回倒数第五个节点,也就是返回链表的头节点,直接将传入的参数返回即可
    • len > k
      • 这是这道题的一般情况,比如:链表的长度是5,返回倒数第2个节点,则需要从节点开始,调用tmp = tmp.next这句代码len-k

代码

import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 *   public ListNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * @param pHead ListNode类
     * @param k     int整型
     * @return ListNode类
     */
    public ListNode FindKthToTail(ListNode pHead, int k) {

		//用len来记录链表的长度
        int len = 0;
        ListNode tmp = pHead;
        while (tmp != null) {
            len++;
            tmp = tmp.next;
        }
        
        if (k > len) {
            return null;
        }

        if (k == len) {
            return pHead;
        }

        tmp = pHead;
        for (int i = 1; i <= (len - k); i++) {
            tmp = tmp.next;
        }
        return tmp;
    }
}

3.2 方案二(双指针)

思路

这个题目也可以反过来思考,假设有两个指针,其中一个指针就指在倒数第k个节点上,另一个指针指在链表的结尾。

假设k=2,也就是返回倒数第二个节点,按照上面的思路,可以画出下图,两个指针之间的距离正好也是2。

在这里插入图片描述

现在把slow和fast两个指针一起向前移动,让slow放在头节点的位置,slow和fast两指针之间的间隔保持不变。
在这里插入图片描述

再往前倒推一步,刚开始的时候slow和fast都指向第一个节点,然后fast先向后移动k次,然后slow和fast再一起移动,这样,当fast指向链表末尾(也就是在最后一个节点,再执行一次.next操作后)的时候,slow指向的位置就是倒数第k个节点。

下面是动态展示:

在这里插入图片描述

代码

import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 *   public ListNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * @param pHead ListNode类
     * @param k     int整型
     * @return ListNode类
     */
    public ListNode FindKthToTail(ListNode pHead, int k) {

        ListNode fast = pHead;
        //fast指针先走k步
        for (int i = 1; i <= k; i++) {
            if (fast != null) {
                fast = fast.next;
            } else {
                //说明 k 大于 链表的长度
                return null;
            }
        }

        ListNode slow = pHead;
        while (fast != null) {
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值