503. 下一个更大元素 II - leetcode刷题(C++)

一、题目

503. 下一个更大元素 II

二、分析

1、 暴力破解就不解释了
2 、单调栈:把循环数复制一份:

[2, 1, 3] -> [2, 1, 3, 2, 1]
n -> 2n-1

就变成了为 [2, 1, 3, 2, 1] 这个有重复数值的,非循环数组找下一个更大元素的问题。找完之后,只要截断n以后的数据即可。
那么新问题就是:有重复数据的数组,为其寻找下一个更大元素。
旧题变新题,你说神奇不神奇?
思路仍然是单调栈的思路,只不过,栈内要记录下标和数值的 pair。所以在此我选择使用 vector 代替之前的 unordered_map
3、官网解答:当然了,细心的朋友可能已经看出来了,记录下标,通过 nums 自然就能得到 nums[i]。这也就是官方解答。单调栈中存放数组下标。这个方法对于有重复数字的数组是通用的。此做法就是上述第二种做法的简化版,降低了存储开销,还省去了最后的拷贝过程,降低了时间开销。

三、代码

  1. 暴力
class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        vector<int> res;
        bool isfound = false;
        for(int i = 0, j = 0; i < nums.size(); i++){
            isfound = false;
            for(j = (i == nums.size()-1) ? 0 : i+1; 
                j != i; j = (j==nums.size()-1) ? 0 : j+1)
            { // 注意 j 的变化即可
                if(nums[j] > nums[i]){
                    res.push_back(nums[j]);
                    isfound = true;
                    break;
                }
            }
            if(!isfound) res.push_back(-1);
        }
        return res;
    }
};

执行用时: 432 ms, 在所有 C++ 提交中击败了6.83%的用户
内存消耗: 22.9 MB, 在所有 C++ 提交中击败了41.18%的用户

  1. 单调栈
class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        int n(nums.size());
        if(n == 0) return vector<int>();
        vector<pair<int, int>> numtwo(2*n-1);
        stack<pair<int, int>> s2;
        //栈不仅记录了数组值,还记录了下标,目的是存结果的 vector 中按 nums 下标有序存放。
        s2.push(make_pair(0, nums[0]));
    
        for (int i = 1; i < 2 * n - 1; i++)
        {
        	// 虽然说是数组扩展到 2n-1,但是实际取数组值的时候,采用 i % n。
            while (!s2.empty() && s2.top().second < nums[i % n])
            {
            	// 栈中 pair 的 first 值为nums中的下标,second为此下标的数组值。
                numtwo[s2.top().first] = make_pair(s2.top().second, nums[i % n]);
                s2.pop();
            }
            s2.push(make_pair(i,nums[i % n]));
        }
        // 处理那些没有解的元素
        while (!s2.empty())
        {
            numtwo[s2.top().first] = make_pair(s2.top().second, -1);
            s2.pop();
        }
        vector<int> res;
        // 拷贝到结果中,截断到n
        for(int i = 0; i < n; i ++){
            res.push_back(numtwo[i].second);
        }
        return res;
    }
};

执行用时:48 ms, 在所有 C++ 提交中击败了64.89%的用户
内存消耗:25.2 MB, 在所有 C++ 提交中击败了5.04%的用户

  1. 官网的复现
class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        int n(nums.size());
        // if(n == 0) return vector<int>(); //不加这一句就40ms了!!!!!????
        vector<int> numtwo(n,-1);
        stack<int> s2;
    
        for (int i = 0; i < 2 * n - 1; i++)
        {
            while (!s2.empty() && nums[s2.top()] < nums[i % n])
            {
                numtwo[s2.top()] = nums[i % n];
                s2.pop();
            }
            s2.push(i % n);
        }
        return numtwo;
    }
};

执行用时:40 ms, 在所有 C++ 提交中击败了81.25%的用户
内存消耗:22.4 MB, 在所有 C++ 提交中击败了90.86%的用户

引用中的代码片段是一个递归函数,名为beautifulArray,它接受一个整数n作为参数,并返回一个vector<int>类型的结果。这个函数用于生成一个长度为n的漂亮数组,漂亮数组满足以下条件:如果将其划分为两个任意长度的子数组,那么两个子数组的元素之和不相等。 函数的实现思路是通过递归,将问题划分为两个子问题,然后合并子问题的解。首先判断n是否等于1,如果等于1,则直接返回一个包含1的数组。否则,将n减1后的一半传入递归函数beautifulArray,得到一个漂亮数组res1。然后将n的一半传入递归函数beautifulArray,得到另一个漂亮数组res2。最后,将res1中的每个元素乘以2并减去1,然后与res2中的每个元素乘以2合并到结果数组res中。 引用中的代码片段是一个函数,名为translateNum,它接受一个整数num作为参数,并返回一个整数。这个函数用于计算将整数num翻译成字符串的不同方法数。 函数的实现思路是将整数num转换为字符串str,然后创建一个长度为str.size()-1的动态数组dp,用于记录不同位置的翻译方法数。然后初始化dp和dp[1]为1,表示前两位数字的翻译方法数。接下来,从第三位数字开始遍历字符串str,如果当前数字与前两位数字可以构成一个在10到25之间的整数,则将dp[i]的值设置为dp[i-1]+dp[i-2],表示当前位置的翻译方法数为前一位和前两位数字的翻译方法数之和。最后,返回dp最后一个元素的值,即为翻译整数num的不同方法数。 引用中的代码片段是一个函数,名为numberOfArithmeticSlices,它接受一个vector<int>类型的数组nums作为参数,并返回一个整数。这个函数用于计算数组nums中等差子序列的个数。 函数的实现思路是通过动态规划,创建一个与nums长度相同的动态数组dp,用于记录以每个位置为结尾的等差子序列的个数。然后遍历数组nums,从第三个元素开始,判断当前元素与前两个元素是否构成等差数列,如果是,则将dp[i]的值设置为dp[i-1]加1,表示以当前位置为结尾的等差子序列个数为前一位的等差子序列个数加1。最后,返回dp数组中所有元素的和,即为等差子序列的个数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值