【算法】漫画:如何找到链表的倒数第n个结点?

机器学习初学者

共 618字,需浏览 2分钟

 ·

2020-10-20 11:13

9729f2ad2f10516a1515f3ef2c1eb14e.webp

8771c5ad6c57e86a71ae47ca048babbb.webp



—————  第二天  —————

5340015c302aed41024fc5e985de665f.webp

7c80965aa12065253878d641c52bcd91.webp

8ddd9442fed261df88ad22735687945e.webp


什么意思呢?我们以下面这个链表为例:


951fdd39d5713d6383a0d3ac4a1e23f2.webp

给定链表的头结点,但并不知道链表的实际长度,要求我们找到链表的倒数第n个结点。


假设n=3,那么要寻找的结点就是元素1:


dd51369d911f931959383212a557c23d.webp

d965f3ce7205934559beaa1dd9e26c91.webp

ced44503b40c06c853fe0062451a994e.webp


9980865bd882bdfac3fd2d87b077927e.webp

0076651e0154f590adc1472b35014412.webp

b7ad7c16c429186e799c4c9d7d105864.webp

761f0bbd56810d24e0e4933718b3ba47.webp


如何利用队列呢?小灰的思路如下:


1.创建一个长度为n的队列,遍历原始链表,让结点逐一进入队列:


1de24a0b49b83616ef3125b4b517c10c.webp


2.当队列已满时,让队尾元素出队,新结点入队:


eb50b54c69b09e7d3cc249fd53a63831.webp


3.当链表全部结点遍历完毕时,队尾的元素就是倒数第n个结点(因为队列长度是n):


5690974103c3abe302637cff051c221c.webp


923f133fa8c72fe6dcefa938a5e6e031.webp

8bd4e203da0c044e81ae81a0f5d20a5f.webp

5bc8b02253ce60e1377157d7d450420d.webp



————————————

be8a93ed75d8b276071410c33d3e2f2b.webp

f4afa1786f90c52217e14bf72939fa8a.webp

7f58be4c0f06dd365bbdf26ddae66cb3.webp

90392ea9c32b06d355db0bab54ddda5c.webp

b1f724af8e838dc68f3ca4c7802bbec7.webp

aa6e005ad4269cf2f0482ccacbb0be35.webp



首先,我们创建两个指针P1和P2,P1指向链表的头结点,P2指向链表的正数第n个结点(也就是例子中的第3个结点):

47dd9da2b97bee7fefbfeebdd45236fb.webp


接下来,我们让指针P1和P2同时循环右移,每次右移一步,直到指针P2移动到链表的末尾:


681b43704158d4924780ada97d09940d.webp

29c948a712f202c4f742e5c7faf0f059.webp


此时,由于P2指向链表的尾结点,且P1和P2的距离是n-1,因此P1所指的结点就是我们要寻找的链表倒数第n个结点:


5dce476308fea27dbc86ec74b479c5c2.webp


显然,这个方法从头到尾只需要对链表做一次遍历,而且仅仅使用了两个指针,算法的空间复杂度是O(1)。

2928a082296ac10406286fa3a5b777ef.webp

8094f9c01539fc64cceda7c2aa7d4847.webp



public class NthFromEnd {
    public static Node findNthFromEnd(Node head, int n){
        Node p1 = head;
        Node p2 = head;
        //把p2指针移动到正数第n个结点
        for(int i=1; i            p2 = p2.next;
            if(p2 == null){
                throw new IllegalArgumentException("参数n超出链表长度!");
            }
        }
        //p1和p2一起右移,直到p2指向链表尾结点
        while (p2.next != null){
            p1 = p1.next;
            p2 = p2.next;
        }
        return p1;
    }

    //快速创建链表
    private static Node buildLinkList(int[] array){
        Node head = new Node(array[0]);
        Node p = head;
        for(int i=1; i            p.next = new Node(array[i]);
            p = p.next;
        }
        return head;
    }

    //链表节点
    private static class Node {
        int data;
        Node next;

        Node(int data) {
            this.data = data;
        }
    }

    public static void main(String[] args) {
        int[] inputs = {5,3,7,2,4,1,9,8};
        Node head = buildLinkList(inputs);
        Node node = findNthFromEnd(head,3);
        System.out.println("链表倒数第3个元素是:" + node.data);
    }

}


9e65f8b14e2998db4cd650805b7ac181.webp

4a29bcdd7f90d6857d4b5bd9db6cdcb2.webp

9afe1c332e6224b61232991bd5859d41.webp

b23e4edde3e6e57eb66e1eed66820152.webp

5658182160b3d88c9bce26f9efc5ddd3.webp

b213a1e20c0edc3daa048e8142c98337.webp



—————END—————



往期精彩回顾





浏览 19
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报