Java语言实现单链表中的倒数第K个元素
单链表是一种常用的数据结构,它由一系列节点组成,每个节点包含一个数据域和一个指向下一个节点的指针。本文将介绍如何使用Java语言找出单链表中的倒数第K个元素,包括使用多种方法进行实现。
方法一:先计算链表长度,再遍历到倒数第K个节点
这种方法比较简单,我们可以先遍历一遍链表,计算出链表的长度,然后再从头节点开始遍历,直到遍历到倒数第K个节点为止。具体的实现步骤如下:
- 遍历一遍链表,计算出链表的长度
len
。 - 如果
len
小于K,则直接返回null。 - 否则,从头节点开始遍历链表,遍历到第
len-K+1
个节点即可。
下面是使用Java语言实现该方法的代码:
public ListNode findKthToTail(ListNode head, int k) {
if (head == null || k <= 0) {
return null;
}
int len = 0;
ListNode p = head;
while (p != null) {
len++;
p = p.next;
}
if (len < k) {
return null;
}
p = head;
for (int i = 0; i < len - k; i++) {
p = p.next;
}
return p;
}
其中,ListNode
表示单链表的节点,包含一个数据域和一个指向下一个节点的指针。head
表示链表的头节点,k
表示要查找的倒数第K个元素的位置。
在实现中,我们首先判断链表是否为空或K是否小于等于0,如果是,则直接返回null。然后,我们遍历一遍链表,计算出链表的长度len
。接着,如果len
小于K,则直接返回null。否则,我们再从头节点开始遍历链表,遍历到第len-K+1
个节点即可。最后,返回该节点即可。
方法二:使用快慢指针
这种方法比较巧妙,我们可以使用两个指针,分别指向链表的头节点和倒数第K个节点,然后将第一个指针向前移动K个位置,最后将两个指针同时向前移动,直到第一个指针到达链表的末尾。具体的实现步骤如下:
- 定义两个指针
p
和q
,初始时都指向链表的头节点。 - 将指针
p
向前移动K个位置,并检查指针p
是否到达链表的末尾。如果没有到达末尾,继续执行步骤3;否则,直接返回null。 - 将指针
p
和q
同时向前移动,直到指针p
到达链表的末尾。 - 此时,指针
q
指向的节点就是倒数第K个节点。
下面是使用Java语言实现该方法的代码:
public ListNode findKthToTail(ListNode head, int k) {
if (head == null || k <= 0) {
return null;
}
ListNode p = head;
ListNode q = head;
for (int i = 0; i < k - 1; i++) {
if (p.next != null) {
p = p.next;
} else {
return null;
}
}
while (p.next != null) {
p = p.next;
q = q.next;
}
return q;
}
其中,ListNode
表示单链表的节点,包含一个数据域和一个指向下一个节点的指针。head
表示链表的头节点,k
表示要查找的倒数第K个元素的位置。
在实现中,我们首先判断链表是否为空或K是否小于等于0,如果是,则直接返回null。然后,我们定义两个指针p
和q
,初始时都指向链表的头节点。接着,我们将指针p
向前移动K个位置,并检查指针p
是否到达链表的末尾。如果没有到达末尾,我们将指针p
和q
同时向前移动,直到指针p
到达链表的末尾。最后,返回指针q
所指向的节点即可。
方法三:使用栈
这种方法比较简单,我们可以使用栈来存储链表中的所有节点,然后从栈顶开始弹出K个节点即可。具体的实现步骤如下:
- 定义一个栈,用于存储链表中的所有节点。
- 遍历链表,将每个节点压入栈中。
- 从栈顶开始弹出K个节点,最后弹出的节点就是倒数第K个节点。
下面是使用Java语言实现该方法的代码:
public ListNode findKthToTail(ListNode head, int k) {
if (head == null || k <= 0) {
return null;
}
Stack<ListNode> stack = new Stack<>();
ListNode p = head;
while (p != null) {
stack.push(p);
p = p.next;
}
if (stack.size() < k) {
return null;
}
ListNode node = null;
while (k > 0) {
node = stack.pop();
k--;
}
return node;
}
其中,ListNode
表示单链表的节点,包含一个数据域和一个指向下一个节点的指针。head
表示链表的头节点,k
表示要查找的倒数第K个元素的位置。
在实现中,我们首先判断链表是否为空或K是否小于等于0,如果是,则直接返回null。然后,我们定义一个栈,用于存储链表中的所有节点。接着,我们遍历链表,将每个节点压入栈中。如果栈的大小小于K,则直接返回null。否则,我们从栈顶开始弹出K个节点,最后弹出的节点就是倒数第K个节点。最后,返回该节点即可。
三种方法的时间复杂度均为O(N),其中N为链表的长度。但是,方法二和方法三的空间复杂度都为O(N),而方法一的空间复杂度为O(1)。因此,如果空间复杂度比较敏感,可以选择方法一。