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

LeetCode - 496 下一个更大元素 I

题目来源

496. 下一个更大元素 I - 力扣(LeetCode)

题目描述

nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素。

给你两个 没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集。

对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j] 的 下一个更大元素 。如果不存在下一个更大元素,那么本次查询的答案是 -1 。

返回一个长度为 nums1.length 的数组 ans 作为答案,满足 ans[i] 是如上所述的 下一个更大元素。

示例1

输入:nums1 = [4,1,2], nums2 = [1,3,4,2].
输出:[-1,3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:
- 4 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
- 1 ,用加粗斜体标识,nums2 = [1,3,4,2]。下一个更大元素是 3 。
- 2 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。

示例2

输入:nums1 = [2,4], nums2 = [1,2,3,4].
输出:[3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:
- 2 ,用加粗斜体标识,nums2 = [1,2,3,4]。下一个更大元素是 3 。
- 4 ,用加粗斜体标识,nums2 = [1,2,3,4]。不存在下一个更大元素,所以答案是 -1 。

提示

  • 1 <= nums1.length <= nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 104
  • nums1和nums2中所有整数 互不相同
  • nums1 中的所有整数同样出现在 nums2 中

题目解析

本题可以使用 “单调栈” 解题。

单调栈,即栈内(从栈底到栈顶)元素呈现单调递减或单调递增性质。

本题要求每个元素的下一个更大元素,则可以使用单调递减栈

具体应用逻辑如下:

  • 遍历 nums 数组的每个元素 num,尝试压入 stack,但是压栈前,需要和 stack.top 栈顶元素比较大小:
  1. 若 stack 为空 或者 num ≤ stack.top,则 num 压栈后,不会破坏 stack 的(非严格)单调递减性质,此时 num 可以直接压栈。
  2. 若 num > stack.top,则 num 压栈后,会破坏 stack 的单调递减性质,此时我们应该将 stack.top 弹出。

    stack.top 弹栈的同时,意味着 stack.top 元素找到了它的下一个更大元素(即:num)。

    stack.top 弹栈完成后,此时 num 还需要继续和新的栈顶元素进行比较大小,循环上面逻辑,直到 stack 为空或者 num ≤ stack.top,才能将 num 压入 stack。

C算法源码

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* nextGreaterElement(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
    int nextBigger[10001];
    for (int i = 0; i <= 10000; i++) {
        nextBigger[i] = -1;
    }

    // (非严格)单调递减栈, 即栈底(索引0位置) 到栈顶(索引stack_size-1位置)的元素是(非严格)单调递减的
    int stack[1000];
    int stack_size = 0;

    // 遍历 nums2 的元素 nums2[i]
    for (int i = 0; i < nums2Size; i++) {
        // 若 stack 非空 且 nums2[i] > stack.top, 则此时 nums2[i] 压栈会破坏 stack 的(非严格)单调递减性质
        while (stack_size > 0 && nums2[i] > stack[stack_size - 1]) {
            // 因此我们需要将 stack.top 弹栈, 弹栈的同时,我们也找到了 stack.top 的下一个更大元素(即为:nums2[i])
            nextBigger[stack[--stack_size]] = nums2[i];
        }

        // 当 stack 为空 或 nums2[i] ≤ stack.top,则此时 nums2[i] 压栈不会破坏 stack 的(非严格)单调递减性质
        stack[stack_size++] = nums2[i];
    }

    int* ans = (int*) malloc(sizeof(int) * nums1Size);
    for (int i = 0; i < nums1Size; i++) {
        ans[i] = nextBigger[nums1[i]];
    }

    *returnSize = nums1Size;

    return ans;
}

C++算法源码

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        map<int, int> nextBigger;

        // (非严格)单调递减栈, 即栈底到栈顶的元素是(非严格)单调递减的
        deque<int> stack;

        // 遍历 nums2 的元素 num
        for (int num : nums2) {
            // 若 stack 非空 且 num > stack.top, 则此时 num 压栈会破坏 stack 的(非严格)单调递减性质
            while (!stack.empty() && num > stack.back()) {
                // 因此我们需要将 stack.top 弹栈, 弹栈的同时,我们也找到了 stack.top 的下一个更大元素(即为:num)
                nextBigger[stack.back()] = num;
                stack.pop_back();
            }

            // 当 stack 为空 或 num ≤ stack.top,则此时 num 压栈不会破坏 stack 的(非严格)单调递减性质
            stack.push_back(num);
        }

        vector<int> ans(nums1.size());
        for (int i = 0; i < nums1.size(); i++) {
            if (nextBigger.find(nums1[i]) != nextBigger.end()) {
                ans[i] = nextBigger[nums1[i]];
            } else {
                ans[i] = -1;
            }
        }

        return ans;
    }
};

JS算法源码

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var nextGreaterElement = function (nums1, nums2) {
    const nextBigger = {};

    // (非严格)单调递减栈, 即栈底到栈顶的元素是(非严格)单调递减的
    const stack = [];
    
    // 遍历 nums2 的元素 num
    for (let num of nums2) {
        // 若 stack 非空 且 num > stack.top, 则此时 num 压栈会破坏 stack 的(非严格)单调递减性质
        while (stack.length > 0 && num > stack.at(-1)) {
            // 因此我们需要将 stack.top 弹栈, 弹栈的同时,我们也找到了 stack.top 的下一个更大元素(即为:num)
            nextBigger[stack.pop()] = num;
        }

        // 当 stack 为空 或 num ≤ stack.top,则此时 num 压栈不会破坏 stack 的(非严格)单调递减性质
        stack.push(num);
    }

    const ans = new Array(nums1.length);
    for (let i = 0; i < nums1.length; i++) {
        ans[i] = nextBigger[nums1[i]] ?? -1;
    }

    return ans;
};

Java算法源码

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        HashMap<Integer, Integer> nextBigger = new HashMap<>();

        // (非严格)单调递减栈, 即栈底到栈顶的元素是(非严格)单调递减的
        ArrayDeque<Integer> stack = new ArrayDeque<>();

        // 遍历 nums2 的元素 num
        for (int num : nums2) {
            // 若 stack 非空 且 num > stack.top, 则此时 num 压栈会破坏 stack 的(非严格)单调递减性质
            while (!stack.isEmpty() && num > stack.peek()) {
                // 因此我们需要将 stack.top 弹栈, 弹栈的同时,我们也找到了 stack.top 的下一个更大元素(即为:num)
                nextBigger.put(stack.pop(), num);
            }

            // 当 stack 为空 或 num ≤ stack.top,则此时 num 压栈不会破坏 stack 的(非严格)单调递减性质
            stack.push(num);
        }

        int[] ans = new int[nums1.length];
        for (int i = 0; i < nums1.length; i++) {
            ans[i] = nextBigger.getOrDefault(nums1[i], -1);
        }

        return ans;
    }
}

 

Python算法源码

class Solution(object):
    def nextGreaterElement(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        nextBigger = {}

        # (非严格)单调递减栈, 即栈底到栈顶的元素是(非严格)单调递减的
        stack = []

        # 遍历 nums2 的元素 num
        for num in nums2:
            # 若 stack 非空 且 num > stack.top, 则此时 num 压栈会破坏 stack 的(非严格)单调递减性质
            while stack and num > stack[-1]:
                # 因此我们需要将 stack.top 弹栈, 弹栈的同时,我们也找到了 stack.top 的下一个更大元素(即为:num)
                nextBigger[stack.pop()] = num
            
            # 当 stack 为空 或 num ≤ stack.top,则此时 num 压栈不会破坏 stack 的(非严格)单调递减性质
            stack.append(num)
        
        ans = []
        for num in nums1:
            ans.append(nextBigger.get(num, -1))
        
        return ans

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

相关文章:

  • ChromeDriver驱动下载地址更新(保持最新最全)
  • 【服务器组件】如何辨别服务器组件
  • 探索Python网络请求新纪元:httpx库的崛起
  • docker 安装之 windows安装
  • Excel单元格中自适应填充多图
  • vue2+3 —— Day5/6
  • 【React】Ant Design 5.x版本drawer抽屉黑边问题
  • 利用ChatGPT实现的生成式人工智能自动化控制系统
  • RabbitMQ的高级特性-限流
  • 英集芯IP5911:集成锂电池充电管理和检测唤醒功能的低功耗8位MCU芯片
  • axios proxy 和 httpsAgent 的使用差异案例详解
  • Vue发送邮件攻略:从搭建到实现详细步骤?
  • asp.net mvc core 路由约束,数据标记DataTokens
  • elasticsearch基础知识、go如何操作elasticsearch
  • EP41 我的评分和我的下载公用分类列表
  • C++游戏开发详解:从入门到实践
  • 解决 Sqoop 导入 Hive 时时间字段精度丢失问题
  • 字母象形:十分有趣的单词扩展逻辑
  • Linux基础(四):文件权限与目录配置
  • vulhub Jboss 漏洞攻略
  • 华为OD真题机试-英文输入法(Java)
  • MySQL9个连接:left join、inner join等
  • RabbitMQ常用管理命令及管理后台
  • 深度学习推理的技术实现与优化策略
  • 达梦数据库导入导出统计信息
  • 【tower-boot 系列】开源RocketMQ和阿里云rockerMq 4.x和5.x集成 (一)