剑指offer-链表中倒数第k个结点

链表中倒数第k个结点

一、题目描述

输入一个链表,输出该链表中倒数第k个结点。

二、题目的思路

这道题让我想到了单链表逆置的题目。

思路1

将整个链表进行逆转,要找到第k个结点只需要将新的链表遍历一下就可以了。

思路2

开辟一个足够大的数组,将链表有序的放入数组,要知道倒数第k个结点,在数组中非常简单。但是这个方法在实际应用中不采用,因为内存中很可能有很多无效的结点,全部放入新的数组,非常浪费空间。

思路3

和思路2类似,用栈的方式存储链表的值,再依次弹出k次就是第k个结点。

貌似思路1的思路很好,很完美了,但是问题来了。如果没有给定链表是带头节点的还是不带头节点的,问题就变得麻烦了。两种处理方式有一些差异,那怎么样做到无差异化呢。

思路4

找两个指针都指向第一个结点(不管是头结点还是首结点)然后遍历,遍历时,让第一个指针往后走k-1步,到达第k个结点,这时候开始两个指针一起动。当第一个结点到达末尾时,第二指针所在的位置就是倒数第k个结点。

三、算法实现

3.1、Java实现

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

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        if(head==null||k<=0){
            return null;
        }
        ListNode pre=head;
        ListNode last=head;
        for(int i=1;i<k;i++){
            if(pre.next!=null){
                pre=pre.next;
            }else{
                return null;
            }
        }
        while(pre.next!=null){
            pre = pre.next;
            last=last.next;
        }
        return last;
    }
}

3.2、C++实现版

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(pListHead==nullptr||k<=0)return nullptr;
        ListNode *pre,*last;
        pre=pListHead;
        last=pListHead;
        for(int i=1;i<k;i++){
            if(pre->next==nullptr) return nullptr;
            else pre=pre->next;
        }
        while(pre->next){
            pre=pre->next;
            last=last->next;
        }
        return last;
    }
};

在解决这里的问题的时候,还发现了一个语法上的问题。pnullptr或者pNULL这样的写法,在C++里,p==nullptr等价于!p,p!=nullptr等价于p,当然这种等价是指布尔属性。
因此改进后的代码如下:

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(!pListHead||k<=0)return nullptr;
        ListNode *pre,*last;
        pre=pListHead;
        last=pListHead;
        for(int i=1;i<k;i++){
            if(!pre->next) return nullptr;
            else pre=pre->next;
        }
        while(pre->next){
            pre=pre->next;
            last=last->next;
        }
        return last;
    }
};
posted @ 2019-02-20 15:20  MarkKobs  阅读(260)  评论(0编辑  收藏  举报