开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情
题目描述
给你一个链表的头节点 head 。
对于列表中的每个节点 node ,如果其右侧存在一个具有 严格更大 值的节点,则移除 node 。
返回修改后链表的头节点 head 。
示例 1:
输入:head = [5,2,13,3,8]
输出:[13,8]
解释:需要移除的节点是 5 ,2 和 3 。
- 节点 13 在节点 5 右侧。
- 节点 13 在节点 2 右侧。
- 节点 8 在节点 3 右侧。
解题思路
方法一
取得每个节点后面的最大值,判断是否跳过当前节点(模拟)
因为我们无法根据索引取得链表中的node的值,所以要先把节点的值都放到list集合中;再从后到前遍历集合取得当前值后面的最大值放到一个数组中;最后再根据数组比较当前节点值后后面的最大值判断当前节点是否跳过。
代码
class Solution {
public ListNode removeNodes(ListNode head) {
List<Integer> list = new ArrayList<>();
ListNode curr = head;
while (curr != null) {
list.add(curr.val);
curr = curr.next;
}
int n = list.size();
int maxVal = Integer.MIN_VALUE;
int[] arr = new int[n];
for (int i = list.size() - 1; i >= 0; i--) {
maxVal = Math.max(list.get(i),maxVal);
arr[i] = maxVal;
}
// ans的next指向head
ListNode ans = new ListNode();
ans.next = head;
curr = ans;
int index = 0;
while (head != null) {
if (head.val < arr[index]) { // 跳过当前节点
curr.next = head.next;
} else { // 当前节点不跳过
curr = curr.next;
}
index ++;
head = head.next;
}
return ans.next;
}
}
方法二
这种链表、树的题一般都能使用递归,这题从后到前遍历也能使用,递归的本质就是从后往前解决问题。
代码
class Solution {
public ListNode removeNodes(ListNode head) {
return fun(head);
}
public ListNode fun(ListNode head){
if (head.next == null) return head;
head.next = fun(head.next); // 去找下一个节点,下一个节点的值就是后面的最大值
if(head.val < head.next.val) return head.next; // 下一个节点的值大就直接跳过当前节点
return head; // 返回当前节点
}
}