牛客刷题---JZ22 链表中倒数最后k个结点

链表中倒数最后k个结点


描述

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

在这里插入图片描述

例如输入{1,2,3,4,5},2时,对应的链表结构如下图所示:
在这里插入图片描述

其中蓝色部分为该链表的最后2个结点,所以返回倒数第2个结点(也即结点值为4的结点)即可,系统会打印后面所有的节点来比较。

示例1

输入:{1,2,3,4,5},2
返回值:{4,5}
说明:返回倒数第2个节点4,系统会打印后面所有的节点来比较。

示例2

输入:{2},8
返回值:{}

解法一:反转链表实现

思路: 先反转链表为newHead,倒数第k个变为第k个,然后再用头插法插入newHead中的前k个创建一个新链表kHead,输出。

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

 public ListNode FindKthToTail (ListNode pHead, int k) {
        
        // 一、先反转链表
         // 1、创建新链表
        ListNode newHead=null;
        // 2、接受当前节点
        ListNode cur=pHead;
        // n用于接受链表长度
        int n=0;
        // 3、遍历旧链表
        while(cur!=null){
            // 4、临时保存下一节点
            ListNode temp=cur.next;
            // 5、当前节点,指向新链表头结点
            cur.next=newHead;
            // 6、更新新链表头结点
            newHead=cur;
             // 7、下一节点
            cur=temp;
            n++;
        }
        
        // 二、再次反转链表,输出第k个
        // 1、创建新链表
        ListNode kHead=null; 
        // 2、接受反转后的链表
        ListNode p=newHead;
        // count用于和k比较
        int count=1;
        // 3、判断链表长度是否小于k
        if(n<k){
            return null;
        }
        
       // 4、输入倒数k个结点,后面代码与反转链表时相同,不同的是遍历条件
        while(count<=k){
            ListNode temp2=p.next;
            p.next=kHead;
            kHead=p;
            p=temp2;
             count++;
        }
        return kHead;
    }

复杂度分析:

  • 时间复杂度:O(N)
  • 空间复杂度: O(1)

解法二:快慢指针

  • 第一个指针先移动k步,然后第二个指针再从头开始,这个时候这两个指针同时移动,当第一个指针到链表的末尾的时候,返回第二个指针即可

在这里插入图片描述

   public ListNode FindKthToTail (ListNode pHead, int k) {
      
        // 1、定义快慢指针
        ListNode fast=pHead;
        ListNode slow=pHead;
        
        // 2、快指针先走k步
        int count=1;
        while(count<=k){
            // 如果fast=null说明k大于链表长度
            if(fast==null){
                return null;
            }
             count++;
           fast= fast.next;
        }  
        // 3、双指针同时走
        while(fast!=null){
            fast=fast.next;
            slow=slow.next;
        }
        // 4、返回慢指针
        return slow;
    }

复杂度分析:

  • 时间复杂度:O(N)
  • 空间复杂度: O(1)

解法三:栈实现

  • 把原链表的结点全部压栈,然后出栈返回第k个结点
 public ListNode FindKthToTail (ListNode pHead, int k) {
      
        // 判空
       if (pHead == null || k == 0){
            return null;
        }
        // 1、创建栈
        Stack<ListNode> stack = new Stack<>();
        // 2、链表节点压栈
        while (pHead != null) {
            stack.push(pHead);
            pHead = pHead.next;
        }
        // 3、判断栈的元素是否小于k
        if (stack.size() < k){
            return null;
        }
        // 4、定义返回结点为栈顶结点
        ListNode newHead = stack.pop();
        while (--k > 0) {
            // 5、返回出栈后的第k个结点
          newHead =stack.pop();
        }
        
        return newHead;
    }

复杂度分析:

  • 时间复杂度:O(N)
  • 空间复杂度: O(N)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绿箭柠檬茶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值