【LeetCode】321c:从链表中移除节点

该博客讨论了如何使用单调栈解决LeetCode 321c问题,即从链表中移除右侧存在更大值节点的题目。通过将链表转化为数组并利用单调栈,找到每个元素右边的第一个更大元素,实现链表节点的删除。代码示例展示了如何在O(n)的时间复杂度内完成操作。相关问题提到了739.每日温度,同样涉及单调栈的应用。
摘要由CSDN通过智能技术生成

321c:从链表中移除节点


原题链接: 321c:从链表中移除节点
仅供学习记录。

题目大意

给你一个链表的头节点 head
对于列表中的每个节点 node ,如果其右侧存在一个具有 严格更大 值的节点,则移除node
返回修改后链表的头节点 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

思路

739. 每日温度类似,考察单调栈,转化为对每个元素求右边第一个比它大的元素。
首先将链表转化为数组来处理较为方便,以及定义好虚拟结点dummy便于处理头结点的情况。
在本题的单调栈中,栈顶元素小于栈底元素,即递增(若存在递减的逆序对,则逆序对中的后者是多余的)。

代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNodes(ListNode* head) {
        vector<int> nums;
        auto dummy = new ListNode(-1);
        dummy->next = head;
        
        for(auto cur = head; cur != nullptr; cur = cur->next){
            nums.push_back(cur->val);
        }
        int n = nums.size();
        
        vector<int> res(n, -1);

        stack<int> stk;//存储的是下标
        for(int i = n - 1; i >= 0; i -- ){
            while(stk.size() && nums[i] >= nums[stk.top()]) stk.pop();
            if(stk.size()) res[i] = nums[stk.top()];
            stk.push(i);
        }
        // for(const auto &c : res)    cout << c << " ";
        // cout << endl;
        int idx = 0;
        for(auto cur = dummy; cur != nullptr; cur = cur->next){
            auto p = cur;
            while(p->next && res[idx] > 0){
                p = p->next;
                idx ++;
            }
            cur->next = p->next;
            
            idx ++;
        }
        
        return dummy->next;
    }
};

时间复杂度

O(n)

相关问题

739. 每日温度
496下一个更大元素I

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值