下一个更大元素

题目

  给你两个没有重复元素的数组 n u m s 1 nums1 nums1 n u m s 2 nums2 nums2,其中 n u m s 1 nums1 nums1 n u m s 2 nums2 nums2的子集。请你找出 n u m s 1 nums1 nums1中每个元素在 n u m s 2 nums2 nums2中的下一个比其大的值。 n u m s 1 nums1 nums1中数字 x x x的下一个更大元素是指 x x x n u m s 2 nums2 nums2中对应位置的右边的第一个比 x x x大的元素。如果不存在,对应位置输出 -1 。

解法一:两层循环,时间复杂度 O ( m n ) O(mn) O(mn)

遍历 n u m s 1 nums1 nums1;
第一个while,找到在元素 x x x n u m s 2 nums2 nums2中位置;
第二个while,找到离 x x x最近的大于 x x x的元素;
没找到,设为-1;

参考代码C++:

vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) 
{
    int m = nums1.size();
    int n = nums2.size();

    vector<int> ret(m, -1);
    for(int i = 0;i < m; ++i){
        int j = 0;
        while(nums1[i] != nums2[j]){
            ++j;
        }

        while(j < n && nums1[i] >= nums2[j]){
            ++j;
        }

        if(j < n){
            ret[i] = nums2[j];
        }
    }
    return ret;
}

解法二:栈,时间复杂度 O ( m + n ) O(m+n) O(m+n)

遍历 n u m s 2 nums2 nums2
使用单调栈辅助1,找到每个元素的下一个最大值
使用map存储( O ( 1 ) O(1) O(1)时间内查询),「key」: n u m s 2 [ i ] nums2[i] nums2[i],「value」: 下一个最大值
遍历 n u m s 1 nums1 nums1,从map中查询其对应的下一个最大值。

参考代码C++

vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2)
{
	int m = nums1.size();
	 int n = nums2.size();
	
	 stack<int> monoStk;
	 map<int,int> dict;
	
	 for(int i = 0; i < n; ++i){
	     while(!monoStk.empty() && monoStk.top() < nums2[i]){
	         int tmp = monoStk.top();
	         dict[tmp] = nums2[i];  // 找到tmp的下一个大于它的值为nums2[i]
	         monoStk.pop();
	     }
	     monoStk.push(nums2[i]);
	 }
	
	 vector<int> ret(m, -1);
	
	 for(int i = 0; i < m; ++i){
	     if(dict.count(nums1[i])){
	         ret[i] = dict[nums1[i]];
	     }
	 }
	 return ret;
}

  1. 符合单调栈的模式:a. 下一个更大的数;b. 队列中某个元素,找离它左右两边最近的大于(小于)它的元素。c. 柱状图中,找到临近的高于(低于)它的柱子。等等,都可以使用单调栈在一次遍历过程中找到所有元素满足条件的值。 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值