JZ22 链表中倒数最后k个结点

题目:
链表中倒数最后k个结点

题解:链表无法逆序访问,也不能通过下标直接访问。故不能逆序遍历链表得到最后k个结点。

解法一:遍历链表用ArrayList存储每一个节点,然后通过下标访问。
当k大于链表长度或者k=0时返回null
倒数第k个节点就是正序list.size()-k个节点。

 public ListNode FindKthToTail (ListNode pHead, int k) {
        List<ListNode> list = new ArrayList<>();
        while(pHead!=null){
            list.add(pHead);
            pHead=pHead.next;
        }
        if(k>list.size()||k==0){
            return null;
        }
        return list.get(list.size()-k);
    }

复杂度分析:
时间复杂度:O(n),总共遍历n个链表元素
空间复杂度:O(n),list存储n个链表元素

解法二:快慢双指针
双指针指的是在遍历的过程中,使用两个指针遍历(特殊情况甚至可以多个),两个指针或是同方向访问两个链表、或是同方向访问一个链表(快慢指针)、或是相反方向扫描(对撞指针)。

构造两个快慢指针,使其之间的距离一直为k,那么当快指针到达链表尾部的时候,慢指针刚好处于倒数第k个位置。

public ListNode FindKthToTail (ListNode pHead, int k) {
        ListNode fast = pHead;
        ListNode slow = pHead;
        while (k > 0 && fast != null) {
            fast = fast.next;
            k--;
        }
        if (k > 0) {
            return null;
        }
        while (fast != null) {
            slow = slow.next;
            fast = fast.next;
        }
        return slow;
    }

第一个while循环,正常情况下k=0,fast!=null,但是如果k大于链表的长度,则fast=null,k>0,属于异常数据,所以在while循环外做了一次k是否大于0的判断。

复杂度分析:
时间复杂度:O(n),总共遍历2n-k个链表元素,O(n)+O(n-k)
空间复杂度:O(1),没有借助额外的内存空间

解法三:先获取到链表长度n,倒数第k个节点就是正向第n-k个节点。解法三与解法一思想有点类似,都是将倒数第k个节点转换成正向第n-k个节点。区别在于解法一用到了额外的存储空间,解法三多遍历了n-k个节点

public ListNode FindKthToTail (ListNode pHead, int k) {
        int size = 0;
        ListNode node = pHead;
        while (node != null) {
            size++;
            node = node.next;
        }
        if (k > size) {
            return null;
        }
        int num = size - k;
        while (num > 0) {
            pHead = pHead.next;
            num--;
        }
        return pHead;
    }

复杂度分析:
时间复杂度:O(n),总共遍历2n-k个链表元素,O(n)+O(n-k)
空间复杂度:O(1),没有借助额外的内存空间

总结:
涉及数据结构:链表
涉及算法:快慢双指针

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值