1.题目描述

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

示例 1:

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

注意: 输入数组的长度不会超过 10000。

2.解法一:暴力法

思路:对于nums中每个元素,直接遍历两遍,确定下一个更大的数存在与否。

代码:运行时间296 ms

class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int n = nums.size();
if(n==) return {}; vector<int> res(n,-);
for(int i=; i<n; ++i){
//下一个更大的数
for(int j=i+; j<*n; ++j){
int num2 = nums[j%n];
if(nums[i] < num2){
res[i]=num2;
break;}
}
}
return res;
}
};

3.解法二:翻倍数组,避免循环(栈)

思路:将原nums数组增长一倍,把nums完整拷贝到增长的区间。因为只需要遍历数组两遍,一定可以确定nums中的每一个元素的下一个更大的数,存在或不存在。

代码:运行时间 144ms

class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
//小技巧:增大一倍数组,不用考虑循环
for(int num : nums){
doubleNums.push_back(num);
}
for(int num : nums){
doubleNums.push_back(num);
} int sz = nums.size();
vector<int> res(sz,-);//sz在运行时才有正确值,所以这两个定义放在函数内部
for(int i=; i<*sz ; ++i){
while(!st.empty() && nums[st.top()]<doubleNums[i]){
res[st.top()]=doubleNums[i];
st.pop();
}
if(i<sz) st.push(i);//只需要原nums中的数字所处位置的【下标】进栈
//因为res的长度必须是sz,超过sz的部分我们只是为了给之前栈中的数字找较大值,所以不能压入栈
}
return res;
}
private:
vector<int> doubleNums;
stack<int> st;
};

4.解法三:取模运算,循环遍历(栈)

思路:基本同理于解法一,数组需要遍历两次(循环遍历),才能确定每一个元素的下一个更大的数字是否存在。这里的改进在于:无需把nums增长一倍并拷贝,而是通过取模运算( i = i % sz),使得遍历的下标 i 不越界。显然,这样更简单。

代码:运行时间96ms

class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int n = nums.size();
vector<int> res(n, -);//技巧:提前都初始化为-1,减少后面重新赋值的步骤 for (int i = ; i < * n; ++i) {
int num = nums[i % n];
while (!st.empty() && nums[st.top()] < num) {
res[st.top()] = num; st.pop();
}
if (i < n) st.push(i);//下标进栈
}
return res;
}
private:
stack<int> st;
};

5.解法四:启发性思路,定义struct元素入栈比较

思路:

  • 定义struct  Item { int index; int v;} ,为的就是协调对应数组元素值与数组下标的关系,便于比较。
  • 上面的解法二和三中的采用的是下标进栈,达到和这里使用struct一样的效果。

代码:运行时间148ms

struct Item {
int index;
int v;
}; class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int n=nums.size();
if(n==) return {}; vector<int> res(n,-);
stack<Item> s;
Item t;
t.index=;
t.v=nums[];
s.push(t);
//遍历第一次
for(int i=;i<n;++i) {
while(!s.empty() && nums[i]>(s.top()).v) {
res[(s.top()).index]=nums[i];
s.pop();
}
t.index=i;
t.v=nums[i];
s.push(t);
}
//遍历第二次
for(int i=;i<n;++i) {
if(s.empty())
break;
while(!s.empty() && nums[i]>(s.top()).v) {
res[(s.top()).index]=nums[i];
s.pop();
}
}
return res;
}
};

参考资料:

1.[LeetCode] Next Greater Element II 下一个较大的元素之二

Leetcode 503. 下一个更大元素 II的更多相关文章

  1. LeetCode 503. 下一个更大元素 II(Next Greater Element II)

    503. 下一个更大元素 II 503. Next Greater Element II 题目描述 给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素.数字 ...

  2. Java实现 LeetCode 503 下一个更大元素 II

    503. 下一个更大元素 II 给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素.数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大 ...

  3. 503. 下一个更大元素 II

    503. 下一个更大元素 II 给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素.数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大 ...

  4. Leetcode 503.下一个更大元素

    下一个更大元素 给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素.数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你 ...

  5. LeetCode 556. 下一个更大元素 III(Next Greater Element III)

    556. 下一个更大元素 III 556. Next Greater Element III 题目描述 给定一个 32 位正整数 n,你需要找到最小的 32 位整数,其与 n 中存在的位数完全相同,并 ...

  6. LeetCode 496. 下一个更大元素 I(Next Greater Element I) 35

    496. 下一个更大元素 I 496. Next Greater Element I 题目描述 给定两个没有重复元素的数组 nums1 和 nums2,其中 nums1 是 nums2 的子集.找到  ...

  7. LeetCode:下一个更大元素I【31】

    LeetCode:下一个更大元素I[31] 题目描述 给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集.找到 nums1 中每个元素在 nums2 中的 ...

  8. 503 Next Greater Element II 下一个更大元素 II

    给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素.数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它 ...

  9. [Leetcode]下一个更大元素II

    题目 给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素.数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地 ...

随机推荐

  1. ES6----Proxy(一)

    Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程. 听起来好像很绕,可以简单这样理解,Proxy相当于 ...

  2. oracle查看用户表

    select table_name from user_tables;

  3. mysql和oracle查询出的一条结果中的多个字段拼接

    1,mysql concat('a','b','c')和concat_ws('a','b','c')的区别:前者如果有某个值为空,结果为空;后者如果有某个值为空,可以忽略这个控制 SELECT con ...

  4. 获取session

    HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()) ...

  5. 啊啊啊 草蛋啊 之前努力一天搞出来的时间算法 被一句pk掉 给我砖头

    package yun3; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.Cale ...

  6. Week2-作业1——关于阅读《构建之法》第1、2、16章的疑问与感悟

    关于阅读<构建之法>第1.2.16章的疑问与感悟 术语解释: 第2章,23页 什么是代码覆盖率? ———————————————————— 在测试中的代码覆盖率是指,你运行测试用例后,走过 ...

  7. Hadoop HA 深度解析

    社区hadoop2.2.0 release版本开始支持NameNode的HA,本文将详细描述NameNode HA内部的设计与实现. 为什么要Namenode HA? 1. NameNode High ...

  8. Keil C51 的printf

    转自:http://blog.csdn.net/zhanglianpin/article/details/44779009 在Keil C51 中使用printf ,首先需要重新实现 putchar( ...

  9. 调整Linux的最大文件打开数

    要调整一下Linux的最大文件打开数,否则squid在高负载时执行性能将会很低.另外,在Linux下面部署应用时,有时候会遇上 Socket/File:Can’t open so many files ...

  10. 二叉查找树ADT--C语言描述

    首先给出此ADT的声明: struct TreeNode; typedef struct TreeNode *Position; typedef struct TreeNode *SearchTree ...