从链表中移除节点
难度:
标签:
题目描述
You are given the head
of a linked list.
Remove every node which has a node with a greater value anywhere to the right side of it.
Return the head
of the modified linked list.
Example 1:

Input: head = [5,2,13,3,8] Output: [13,8] Explanation: The nodes that should be removed are 5, 2 and 3. - Node 13 is to the right of node 5. - Node 13 is to the right of node 2. - Node 8 is to the right of node 3.
Example 2:
Input: head = [1,1,1,1] Output: [1,1,1,1] Explanation: Every node has value 1, so no nodes are removed.
Constraints:
- The number of the nodes in the given list is in the range
[1, 105]
. 1 <= Node.val <= 105
代码结果
运行时间: 312 ms, 内存: 57.9 MB
/*
题目思路:
1. 由于链表的单向特性,我们需要先将链表的节点值存入列表。
2. 通过列表的stream从右向左遍历,维护一个最大值,筛选出符合条件的值。
3. 将筛选出的值重新构建成链表。
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public class Solution {
public ListNode removeNodes(ListNode head) {
List<Integer> values = new ArrayList<>();
while (head != null) {
values.add(head.val);
head = head.next;
}
Collections.reverse(values);
List<Integer> filteredValues = new ArrayList<>();
int max = Integer.MIN_VALUE;
for (int value : values) {
if (value >= max) {
max = value;
filteredValues.add(value);
}
}
Collections.reverse(filteredValues);
ListNode dummy = new ListNode(0);
ListNode current = dummy;
for (int value : filteredValues) {
current.next = new ListNode(value);
current = current.next;
}
return dummy.next;
}
}
解释
方法:
题解采用的是递归方法来解决问题。首先,判断当前节点是否为尾节点,如果是,则直接返回该节点。否则递归调用当前函数处理当前节点的下一个节点。在递归返回后,比较当前节点的值与其下一个节点的值。如果当前节点的值小于下一个节点的值,则说明当前节点应该被移除,因此返回下一个节点。如果不是,则保留当前节点,返回当前节点。这样递归处理可以确保从链表末尾开始逐个检查节点,每次递归返回时都能决定是否保留当前节点。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在递归解决方案中,如何确保递归栈不会因为链表过长而溢出?
▷🦆
递归解决方案中,当链表长度极大时,会存在性能问题吗?如果有,如何优化?
▷🦆
递归返回时,若当前节点值小于下一个节点值,则移除当前节点。在这种情况下,被移除的节点的内存如何处理?是否需要考虑内存泄露问题?
▷🦆
题解中没有处理所有节点相等的情况的特殊逻辑,这是否意味着算法自然支持这种情况?如果是,为什么?
▷