前言给定一个单向链表的头节点,如何获取链表倒数第K个节点(从1)?本文将带大家解决这个问题,欢迎各位有兴趣的开发者阅读本文。思路分析我们用一个例子来进一步分析:准备一个链表,它有6个节点,从头节点开始,它的值分别是:1,3,5,9,15,21。得到倒数第三个节点链表的。遍历链表两次根据单向链表的定义,我们知道要想得到它的某个结点,只能从头结点开始,顺着它的指针向后查找。假设整个链表有n个节点,那么最后的第k个节点就是从头节点算起的第n-k+1个节点。如果我们能得到节点数n,那么我们只需要从头节点往回走n-k+1步即可。如果要得到节点的个数n,需要定义一个变量从头开始遍历链表,每经过一个节点这个变量就加1。也就是说,我们需要遍历链表两次,第一次计算链表的节点数,第二次获取倒数第二个K节点,如下图:第一次到遍历链表,得到链表的长度n=6。链表的第二次遍历在倒数第三个节点(6-3+1)处得到值9。遍历一次链表和遍历链表两次不是解决这个问题的最优方案。让我们换个角度考虑这个问题:准备两个指针。第一个指针从链表头开始向前遍历k-1(3-1=2)步,第二个指针不变。从第k步开始,第二个指针也从链表的头指针开始遍历,两个指针同时向前移动。由于两个指针之间的距离始终保持在k-1,所以当第一个指针到达链表的尾节点时,第二个指针正好指向倒数第二个第k个节点。实现代码通过上面的分析,我们知道了如何利用双指针的思想,只遍历链表一次,就可以得到链表从底部开始的第K个节点。接下来我们看一下代码实现。首先,我们设计一个名为GetLinkedListNode的类:里面有2个私有变量。pNextP1指针;pHeadP2指针。构造函数接受一个参数:链表的头节点。检查参数;修改两个指针的指针:默认指向链表的头节点。exportclassGetLinkedListNode{//p1指针privatepNext:ListNode;//p2指针(与p1指针的距离始终保持在k-1)privatepHead:ListNode;constructor(listHead:ListNode){if(listHead==null){thrownewError("链表头节点不能为空");}//初始化两个指针指向this.pNext=listHead;this.pHead=listHead;}??在上面的代码中,我们使用了一个自定义类型ListNode,它描述了一个链表的节点应该包含哪些属性,对此感兴趣的开发者请移步我的另一篇文章:实现链表和伪装链表。接下来实现获取倒数第二个K节点的功能:接受一个参数K(从1开始),并验证参数的有效性。将p1的指针修改为指向节点k-1,k的范围也要绕开(其值大于链表节点总数)。同步修改p1和p2的指针,直到p1指针指向尾节点,p2指针恰好指向倒数第K个节点。//获取倒数第K个节点getCountdownNode(k:number):ListNode{if(k<=0){thrownewError("获取的底部节点数必须大于0");}//p1指针在前,指向链表的k-1位置for(leti=0;i
