2487. 从链表中移除节点

发布时间:2024年01月04日


2487. 从链表中移除节点
难度: 中等
来源: 每日一题 2024.01.03

给你一个链表的头节点 head

移除每个右侧有一个更大数值的节点。

返回修改后链表的头节点 head

示例 1:

输入:head = [5,2,13,3,8]
输出:[13,8]
解释:需要移除的节点是 5 ,2 和 3 。
- 节点 13 在节点 5 右侧。
- 节点 13 在节点 2 右侧。
- 节点 8 在节点 3 右侧。

示例 2:

输入:head = [1,1,1,1]
输出:[1,1,1,1]
解释:每个节点的值都是 1 ,所以没有需要移除的节点。

提示:

  • 给定列表中的节点数目在范围 [1, 10^5]
  • 1 <= Node.val <= 10^5
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNodes(ListNode head) {

    }
}

分析与题解

  • 栈(先进后出)

    2024年第一篇博客, 开始喽~

    言归正传, 对于这个题目, 我们应该尝试使用栈的方式, 在遍历链表的过程中, 我们需要用栈的形式存储每一个链表节点, 并且为了方便后期的组装, 我们可以尝试双向队列来代替链表, 以便于后边后期从栈底取出元素.

    ArrayDeque<ListNode> deque = new ArrayDeque<ListNode>();
    

    那么什么时候触发删除操作呢? 如果当前节点的值比上一个节点的值大时, 也就是题意中的 每个右侧有一个更大数值的节点, 我们就从双向队列的栈顶依次取值, 直到不满足栈顶的值不大于当前节点的值.

    if (head.val > lastValue) {
        ListNode lastNode = deque.peekFirst();
        while (lastNode != null && lastNode.val < head.val) {
            deque.pollFirst();
            lastNode = deque.peekFirst();
        }
    }
    

    然后就是利用双向队列来重组链表了, 我们需要依次从栈底抛出节点然后组装链表.

    ListNode resultHeader = null, nowNode = null;
    while (!deque.isEmpty()) {
        ListNode node = deque.pollLast();
        if (resultHeader == null) {
            resultHeader = node;
            nowNode = node;
        } else {
            nowNode.next = node;
            nowNode = nowNode.next;
        }
    }
    

    接下来, 我们就看一下整体的题解过程.

    /**
    * Definition for singly-linked list.
    * public class ListNode {
    *     int val;
    *     ListNode next;
    *     ListNode() {}
    *     ListNode(int val) { this.val = val; }
    *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
    * }
    */
    class Solution {
        public ListNode removeNodes(ListNode head) {
            // 用栈实现, 先入栈后出栈
            ArrayDeque<ListNode> deque = new ArrayDeque<ListNode>();
            int lastValue = 0;
            while (head != null) {
                if (head.val > lastValue) {
                    ListNode lastNode = deque.peekFirst();
                    while (lastNode != null && lastNode.val < head.val) {
                        deque.pollFirst();
                        lastNode = deque.peekFirst();
                    }
                }
                deque.addFirst(head);
                lastValue = head.val;
                head = head.next;
            }
            // 搞定之后重组链表
            ListNode resultHeader = null, nowNode = null;
            while (!deque.isEmpty()) {
                ListNode node = deque.pollLast();
                if (resultHeader == null) {
                    resultHeader = node;
                    nowNode = node;
                } else {
                    nowNode.next = node;
                    nowNode = nowNode.next;
                }
            }
            return resultHeader;
        }
    }
    

    复杂度分析:

    • 时间复杂度: O(n * n2), 两层的循环遍历的时间复杂度
    • 空间复杂度: O(n), 双向队列所需要的空间复杂度与链表元素个数成线性关系

    结果如下所示.

文章来源:https://blog.csdn.net/qq_33591200/article/details/135378981
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。