zoukankan      html  css  js  c++  java
  • [LeetCode] 1019. Next Greater Node In Linked List 链表中的下一个较大的结点


    We are given a linked list with head as the first node.  Let's number the nodes in the list: node_1, node_2, node_3, ... etc.

    Each node may have a next larger value: for node_inext_larger(node_i) is the node_j.val such that j > inode_j.val > node_i.val, and j is the smallest possible choice.  If such a j does not exist, the next larger value is 0.

    Return an array of integers answer, where answer[i] = next_larger(node_{i+1}).

    Note that in the example inputs (not outputs) below, arrays such as [2,1,5] represent the serialization of a linked list with a head node value of 2, second node value of 1, and third node value of 5.

    Example 1:

    Input: [2,1,5]
    Output: [5,5,0]
    

    Example 2:

    Input: [2,7,4,3,5]
    Output: [7,0,5,5,0]
    

    Example 3:

    Input: [1,7,5,1,9,2,5,1]
    Output: [7,9,9,9,0,5,0,0]
    

    Note:

    1. 1 <= node.val <= 10^9 for each node in the linked list.
    2. The given list has length in the range [0, 10000].

    这道题给了一个链表,让找出每个结点值的下一个较大的结点值,跟之前的 Next Greater Element INext Greater Element II,和 Next Greater Element III 很类似,不同的是这里不是数组,而是链表,就稍稍的增加了一些难度,因为链表无法直接根据下标访问元素,在遍历链表之前甚至不知道总共有多少个结点。但是无妨,整个思路还是一样的,当然最简单暴力的解法,就是对于每个结点,都遍历后面的所有结点,找出第一个大于的结点值,但这种平方级时间复杂度的解法基本上是无法通过 OJ 的,毕竟这是一道 Medium 难度的题目。这时候就要祭出单调栈这个大杀器了,可以参见博主之前的总结贴 LeetCode Monotonous Stack Summary 单调栈小结,基本上来说,为了达到线性的时间复杂度,这里需要维护一个单调递减的栈,若当前的数字小于等于栈顶元素,则加入栈,若当前数字大于栈顶元素,非常棒,说明栈顶元素的下一个较大数字找到了,标记上,且把栈顶元素移除,继续判断下一个栈顶元素和当前元素的关系,直到当前数字小于等于栈顶元素为止。通过这种方法,就可以在线性的时间内找出所有数字的下一个较大的数字了。思路有了,下面来看具体的代码,这里新建两个数组,res 和 nums 分别保存要求的结果和链表的所有结点值,还需要一个栈 st 和一个变量 cnt(记录当前的数组坐标),然后开始遍历链表,首先把当前结点值加入数组 nums,然后开始循环,若栈不空,且当前结点值大于栈顶元素(注意这里单调栈存的并不是结点值,而是该值在 nums 数组中的坐标值,这是为了更好的在结果 res 中定位),此时用该结点值来更新结果 res 中的对应的位置,然后将栈顶元素移除,继续循环直到条件不满足位置。然后把当前的坐标加入栈中,此时还要更新结果 res 的大小,因为由于链表的大小未知,无法直接初始化 res 的大小,当然我们可以在开头的时候先遍历一遍链表,得到结点的个数也是可以的,参见代码如下:


    class Solution {
    public:
        vector<int> nextLargerNodes(ListNode* head) {
            vector<int> res, nums;
            stack<int> st;
            int cnt = 0;
            while (head) {
                nums.push_back(head->val);
                while (!st.empty() && head->val > nums[st.top()]) {
                    res[st.top()] = head->val;
                    st.pop();
                }
                st.push(cnt);
                res.resize(++cnt);
                head = head->next;
            }
            return res;
        }
    };
    

    Github 同步地址:

    https://github.com/grandyang/leetcode/issues/1019


    类似题目:

    Next Greater Element I

    Next Greater Element II

    Next Greater Element III


    参考资料:

    https://leetcode.com/problems/next-greater-node-in-linked-list/

    https://leetcode.com/problems/next-greater-node-in-linked-list/discuss/265548/C%2B%2B-O(n)-stack

    https://leetcode.com/problems/next-greater-node-in-linked-list/discuss/265508/JavaC%2B%2BPython-Next-Greater-Element


    LeetCode All in One 题目讲解汇总(持续更新中...)

  • 相关阅读:
    过滤器--起步阶段
    常用指令-起步阶段
    模型和控制器-起步阶段
    指令介绍-起步阶段
    AngularJS简介-起步阶段
    c++之helloworld与命名空间
    c++ 之重要性
    一个没曾摸透的程序
    linux中什么是文件结构体?
    很全的linux网络编程技巧
  • 原文地址:https://www.cnblogs.com/grandyang/p/14383745.html
Copyright © 2011-2022 走看看