剑指offer 22:链表中倒数最后K个节点

题目描述:

输入一个长度为 n 的链表,设链表中的元素的值为 ai ,返回该链表中倒数第k个节点。如果该链表长度小于k,请返回一个长度为 0 的链表。

数据范围:0 ≤ n ≤ 10^5,0≤ai​≤10^9,0≤k≤10^9

要求:空间复杂度 O(n),时间复杂度 O(n)

进阶:空间复杂度 O(1),时间复杂度 O(n)

示例1:

输入:{1,2,3,4,5},2

返回值:{4,5}

说明:返回倒数第2个节点4,系统会打印后面所有的节点来比较

示例2:

输入:{2},8

返回值:{}

解法一:快慢指针

思路:

定义两个指针 fast 和 slow 都指向链表的头节点, fast 首先移动 k 步,然后两个指针一起移动,当 fast指针指向链表末尾的时候,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 slow = pHead, fast = pHead;
        //fast先走k步
        while(k-- > 0){
            //如果在走第k步之前链表就指向空,说明链表长度小于k。直接返回null
            if(fast == null){
                return null;
            }
            fast = fast.next;
        }
        //fast和slow一起向后遍历,当fast指向空的时候,slow即为倒数第k个节点
        while(fast != null){
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}

解法二:

思路:

首先遍历一次链表,得到链表的长度,然后通过对比 k 和 len 的大小:

  • 如果 k 大于 len,直接返回 null。
  • 如果 k 小于等于 len,则得到 len - k 的值记为val,再次将指针指向链表的头节点,向后遍历 val 步,即为链表的倒数第 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 cur = pHead;
        //链表的长度
        int len = 0;
        //通过指针遍历链表,得到链表的长度
        while(cur != null){
            len++;
            cur = cur.next;
        }
        //如果k大于链表长度,直接返回
        if(k > len){
            return null;
        }
        //得到需要走的步数
        int val = len - k;
        //指针再次指向链表的头节点
        cur = pHead;
        //向后走val步,即得到链表中倒数第K个节点
        while(val -- > 0){
            cur = cur.next;
        }
        return cur;
    }
}

解法三:栈

思路:

利用栈先进后出的特性,先将元素全部入栈,然后再弹出末尾的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) {
        //用栈来存储节点信息
        Stack<ListNode> stack = new Stack<>();
        //节点元素全部入栈
        while(pHead != null){
            stack.push(pHead);
            pHead = pHead.next;
        }
        //处理特殊情况
        if(k > stack.size() || k ==0){
            return null;
        }
        //弹出元素
        while(k-- > 1){
            stack.pop();
        }
        //返回栈顶元素即为结果
        return stack.peek();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值