链表中倒数第k个节点

剑指offer之链表中倒数第k个节点

题目描述:输入一个链表,输出该链表中倒数第k个结点。

问题分析:本题关于对链表的运用。

解一:没看题解之前,我的想法是,先按顺序遍历链表,并将每个节点的数据按顺序存进数组中,最后读取数组中的位置,并构建包括从该位置开始的后面所有数据的一个新链表,返回该节点,则是我们需要得到的节点。但该方法虽然可以实现本题,但显然并不是很好的方法,首先它使用了数组,开辟了新空间,并且在链表的数据节点中的数据较复杂时,这种做法也不适合。具体实现如下:

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
import java.util.ArrayList;
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        ArrayList<Integer> list = new ArrayList<>();
        ListNode tmp = head;
        while(tmp!=null){
            list.add(tmp.val);
            tmp = tmp.next;
        }
        ListNode node = null;
       
        if(list.size() >= k && k > 0){//如果k>0这种情况没有考虑到,无法通过
            int i = list.size()-k;
            node = new ListNode(list.get(list.size()-k));
            tmp = node;
            while(i < list.size()-1){
                i++;
                ListNode tmp2 = new ListNode(list.get(i));
                tmp.next = tmp2;
                tmp = tmp.next;
            }
            
        }
        return node;
    }
}

解二:先遍历一遍链表,计算出结点个数,倒数第k个节点可以转换为顺数第n-k个节点。这种写法明显比上一种要简洁,且不用开辟额外空间,但其实这也并不是这道题想考我们的:

import java.util.ArrayList;
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        ListNode tmp = head;
        int count = 0;
       while(tmp != null){
           count++;
           tmp = tmp.next;
       }
        if(k > count || k <= 0)//k的取值应考虑到
            return null;
       
        int i = 0;
        tmp = head;
        while(i < (count-k)){
            tmp = tmp.next;
            i++;
        }
        return tmp;
    }
}

解三:
快慢指针
将两个指针同时进行平移,具体过程图解释的比较清楚,就不再用文字解释。中心思想,两个指针之间的节点数包含k个,保持前后两个指针相对位置不变向后开始平移,直到后面的指针为最后一个指针结束。这时,前面的指针就是倒数第k’个元素。该方法的时间复杂度只有O(n),只用遍历一遍指针就能得出结果,具体实现如下:

import java.util.ArrayList;
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        ListNode fast = head,slow = head;
        int i = 0;
        //注:首先判断链表为空与数为零的情况
        if(head == null)
            return null;
        if(k == 0)
            return null;
        while(fast!=null){
            i++;
            if(i >= k){
                break;
            }
            if(fast.next == null){//此处判断fast是否已经为最后一个指针,若为最后一个指针,且循环还未结束,说明链表节点数小于k,返回null
                return null;
            }
            fast = fast.next;
        }
        
        while(fast.next != null){
            slow=slow.next;
            fast=fast.next;
        }
        return slow;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值