当前位置: 首页 > article >正文

LeetCode - 503 下一个更大元素 II

题目来源

503. 下一个更大元素 II - 力扣(LeetCode)

题目描述

给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。

数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1 。

示例

输入: nums = [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数; 
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

输入: nums = [1,2,3,4,3]
输出: [2,3,4,-1,4]

提示

  • 1 <= nums.length <= 10^4
  • -10^9 <= nums[i] <= 10^9

题目解析

本题是 LeetCode - 496 下一个更大元素 I-CSDN博客 升级。大家需要现看懂前面这题,才能继续看本题。

本题相较于 496题 的变化在于,nums 数组是首尾相连的,即 nums[nums.length - 1] 下一个更大元素,可以继续从 nums[0] 开始找。

因此,本题最简单的思路就是,将 496题 的遍历逻辑重复两次。两轮共用一个栈。

  • 第一次遍历结束时,栈中可能会剩余一些未找到下一个更大值的元素。
  • 第二次遍历的目的是:找到第一次结束后,栈中剩余元素的下一个更大值的元素。(PS:因此第二轮遍历时,就可以去除压栈逻辑,仅保留弹栈和比较大小的逻辑)。

C算法源码

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* nextGreaterElements(int* nums, int numsSize, int* returnSize) {
    int* ans = (int*)malloc(sizeof(int) * numsSize);
    for (int i = 0; i < numsSize; i++) {
        ans[i] = -1;
    }

    // stack 记录的是 nums索引, 记录索引要比记录元素本身更好, 因为通过索引可以找到元素
    // stack 是一个单调递减栈, (从栈底到栈顶)栈内元素(索引对应nums元素)呈现单调递减性质
    int stack[10001];
    int stack_size = 0;

    // 循环两遍 nums, 相当于 nums 数组后面又拼接一个 nums数组
    for (int i = 0; i < numsSize * 2; i++) {
        // 避免 i 索引越界
        int j = i % numsSize;

        // 若 stack 非空 且 nums[j] > nums[stack.top], 则此时 nums[j] 压栈会破坏 stack 的(非严格)单调递减性质
        while (stack_size > 0 && nums[j] > nums[stack[stack_size - 1]]) {
            // 因此我们需要将 stack.top 弹栈, 弹栈的同时,我们也找到了 stack.top(索引位置)对应元素 的下一个更大元素(即为:nums[j])
            ans[stack[--stack_size]] = nums[j];
        }
        
        // 当 stack 为空 或 nums[j] ≤ nums[stack.top],则此时 j 压栈不会破坏 stack 的(非严格)单调递减性质
        if(i < numsSize) { // 优化:第一轮遍历完后, stack 栈中剩余的元素(索引位置)都未找到下一个更大值, 因此第二轮遍历的目的只是处理这里栈中剩余元素,即第二轮遍历时,我们无需再压入新元素到栈。
            stack[stack_size++] = j;
        }
    }

    *returnSize = numsSize;

    return ans;
}

C++算法源码

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        vector<int> ans(nums.size(), -1);

        // stack 记录的是 nums索引, 记录索引要比记录元素本身更好, 因为通过索引可以找到元素
        // stack 是一个单调递减栈, (从栈底到栈顶)栈内元素(索引对应nums元素)呈现单调递减性质
        deque<int> stack;

        // 循环两遍 nums, 相当于 nums 数组后面又拼接一个 nums数组
        for (int i = 0; i < nums.size() * 2; i++) {
            // 避免 i 索引越界
            int j = i % nums.size();

            // 若 stack 非空 且 nums[j] > nums[stack.top], 则此时 nums[j] 压栈会破坏 stack 的(非严格)单调递减性质
            while (!stack.empty() && nums[j] > nums[stack.back()]) {
                // 因此我们需要将 stack.top 弹栈, 弹栈的同时,我们也找到了 stack.top(索引位置)对应元素 的下一个更大元素(即为:nums[j])
                ans[stack.back()] = nums[j];
                stack.pop_back();
            }

            // 当 stack 为空 或 nums[j] ≤ nums[stack.top],则此时 j 压栈不会破坏 stack 的(非严格)单调递减性质
            if(i < nums.size()) { // 优化:第一轮遍历完后, stack 栈中剩余的元素(索引位置)都未找到下一个更大值, 因此第二轮遍历的目的只是处理这里栈中剩余元素,即第二轮遍历时,我们无需再压入新元素到栈。
                stack.push_back(j);
            }
        }

        return ans;
    }
};

JS算法源码

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var nextGreaterElements = function (nums) {
    const ans = new Array(nums.length).fill(-1);

    // stack 记录的是 nums索引, 记录索引要比记录元素本身更好, 因为通过索引可以找到元素
    // stack 是一个单调递减栈, (从栈底到栈顶)栈内元素(索引对应nums元素)呈现单调递减性质
    const stack = [];

    // 循环两遍 nums, 相当于 nums 数组后面又拼接一个 nums数组
    for (let i = 0; i < nums.length * 2; i++) {
        // 避免 i 索引越界
        const j = i % nums.length;

        // 若 stack 非空 且 nums[j] > nums[stack.top], 则此时 nums[j] 压栈会破坏 stack 的(非严格)单调递减性质
        while (stack.length > 0 && nums[j] > nums[stack.at(-1)]) {
            // 因此我们需要将 stack.top 弹栈, 弹栈的同时,我们也找到了 stack.top(索引位置)对应元素 的下一个更大元素(即为:nums[j])
            ans[stack.pop()] = nums[j];
        }

        // 当 stack 为空 或 nums[j] ≤ nums[stack.top],则此时 j 压栈不会破坏 stack 的(非严格)单调递减性质
        if(i < nums.length) { // 优化:第一轮遍历完后, stack 栈中剩余的元素(索引位置)都未找到下一个更大值, 因此第二轮遍历的目的只是处理这里栈中剩余元素,即第二轮遍历时,我们无需再压入新元素到栈。
            stack.push(j);
        }
    }

    return ans;
};

Java算法源码

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int[] ans = new int[nums.length];
        Arrays.fill(ans, -1);

        // stack 记录的是 nums索引, 记录索引要比记录元素本身更好, 因为通过索引可以找到元素
        // stack 是一个单调递减栈, (从栈底到栈顶)栈内元素(索引对应nums元素)呈现单调递减性质
        ArrayDeque<Integer> stack = new ArrayDeque<>();

        // 循环两遍 nums, 相当于 nums 数组后面又拼接一个 nums数组
        for (int i = 0; i < nums.length * 2; i++) {
            // 避免 i 索引越界
            int j = i % nums.length;

            // 若 stack 非空 且 nums[j] > nums[stack.top], 则此时 nums[j] 压栈会破坏 stack 的(非严格)单调递减性质
            while (!stack.isEmpty() && nums[j] > nums[stack.peek()]) {
                 // 因此我们需要将 stack.top 弹栈, 弹栈的同时,我们也找到了 stack.top(索引位置)对应元素 的下一个更大元素(即为:nums[j])
                ans[stack.pop()] = nums[j];
            }

            // 当 stack 为空 或 nums[j] ≤ nums[stack.top],则此时 j 压栈不会破坏 stack 的(非严格)单调递减性质
            if(i < nums.length) { // 优化:第一轮遍历完后, stack 栈中剩余的元素(索引位置)都未找到下一个更大值, 因此第二轮遍历的目的只是处理这里栈中剩余元素,即第二轮遍历时,我们无需再压入新元素到栈。
                stack.push(j);
            }
        }

        return ans;
    }
}

Python算法源码

class Solution(object):
    def nextGreaterElements(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        ans = [-1] * len(nums)

        # stack 记录的是 nums索引, 记录索引要比记录元素本身更好, 因为通过索引可以找到元素
        # stack 是一个单调递减栈, (从栈底到栈顶)栈内元素(索引对应nums元素)呈现单调递减性质
        stack = []

        # 循环两遍 nums, 相当于 nums 数组后面又拼接一个 nums数组
        for i in range(len(nums) * 2):
            # 避免 i 索引越界
            j = i % len(nums)

            # 若 stack 非空 且 nums[j] > nums[stack.top], 则此时 nums[j] 压栈会破坏 stack 的(非严格)单调递减性质
            while stack and nums[j] > nums[stack[-1]]:
                # 因此我们需要将 stack.top 弹栈, 弹栈的同时,我们也找到了 stack.top(索引位置)对应元素 的下一个更大元素(即为:nums[j])
                ans[stack.pop()] = nums[j]
            
            # 当 stack 为空 或 nums[j] ≤ nums[stack.top],则此时 j 压栈不会破坏 stack 的(非严格)单调递减性质
            if i < len(nums):  # 优化:第一轮遍历完后, stack 栈中剩余的元素(索引位置)都未找到下一个更大值, 因此第二轮遍历的目的只是处理这里栈中剩余元素,即第二轮遍历时,我们无需再压入新元素到栈。
                stack.append(j)
        
        return ans


http://www.kler.cn/a/320074.html

相关文章:

  • 森林网络部署,工业4G路由器实现林区组网远程监控
  • Java中如何实现对象的深拷贝和浅拷贝?
  • 从前端视角看设计模式之创建型模式篇
  • MLX90640自制热像仪(四) LVGL UI界面设计 移植 SquareLine Studio
  • 实现类似Excel的筛选
  • c++领域展开第十二幕——类和对象(STL简介——简单了解STL)超详细!!!!
  • 使用iTextPDF库实现矩形框和打勾符号(√)
  • 【网络安全】更改参数实现试用计划延长
  • 国内可用ChatGPT-4中文镜像网站整理汇总【持续更新】
  • keepalived+lvs集群
  • 体育馆管理系统|基于SpingBoot+vue的体育馆管理系统(源码+数据库+文档)
  • 微信小程序-分包加载
  • AWS开启MFA,提高安全性
  • 数据库——sql语言学习 查找语句
  • 【CSS】鼠标 、轮廓线 、 滤镜 、 堆叠层级
  • php中根据指定日期获取所在天,周,月,年的开始日期与结束日期
  • 10.2软件工程知识详解下
  • uniapp vue3 使用echarts绘制图表 柱状图等
  • AI搜索软件哪个好,AI搜索引擎工具分享
  • react crash course 2024(2) 创建项目及vscode插件
  • xpath的基本使用,精准定位html中的元素
  • Nginx基础详解2(首页解析过程、进程模型、处理Web请求机制、nginx.conf语法结构)
  • PCL 用八叉树完成空间变化检测
  • 【Android】页面启动耗时统计流程梳理
  • 操作系统知识4
  • Pr 入门系列之五:编辑 - 进阶篇(上)