力扣496. 下一个更大元素 I---单调栈+哈希映射思想

496. 下一个更大元素 I

给定两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。

nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。

示例 1:

输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
    对于num1中的数字4,你无法在第二个数组中找到下一个更大的数字,因此输出 -1。
    对于num1中的数字1,第二个数组中数字1右边的下一个较大数字是 3。
    对于num1中的数字2,第二个数组中没有下一个更大的数字,因此输出 -1。
示例 2:

输入: nums1 = [2,4], nums2 = [1,2,3,4].
输出: [3,-1]
解释:
    对于 num1 中的数字 2 ,第二个数组中的下一个较大数字是 3 。
    对于 num1 中的数字 4 ,第二个数组中没有下一个更大的数字,因此输出 -1 。
 
提示:
nums1和nums2中所有元素是唯一的。
nums1和nums2 的数组大小都不超过1000。

题解:

此题和我写的另一题力扣739. 每日温度–暴力法与单调栈有些类似,有兴趣可以看一下。

首先理解题意,我们是要拿着nums1里面的数去nums2里与之相等的数的位置往后去寻找更大的元素。且题目说明了1是2的子集,那么我们如果直接拿着nums2里面的数在原位置之后找更大的元素的话会方便很多,最后再经过1数组的一个选择即可。

那么怎么完成后者的操作呢?

通过分析可知,这又是一个类似“先进后出”的问题,因此我们可以使用来解决。
本题是一个单调栈的过程。
(通常是一维数组,要寻找任一元素右边(左边)第一个比自己大(小)的元素一般都会采用单调栈思想。)

即构建一个数组模拟栈,用来模拟我们后者操作的“选择”过程

先将nums2数组遍历一下,如果栈为空直接入栈,栈不为空时需要分一下两种情况:

1.此时栈外元素大于栈顶元素,则满足题意“下一个最大元素”,所以将此时二者的对应关系通过制造一个哈希映射存储起来,然后让栈顶元素出栈,继续下面的比对。

2.此时栈外元素小于栈顶元素,则直接入栈即可,因为不满足我们的要求.

经过选择后我们可以通过建立哈希映射数组来保存此时nums2数组各元素与其“下一个最大元素”的对应关系,接着由于我们真正要的是nums1这个nums2的子集数组的情况,因此根据存储的哈希映射进行一个选择即可。

代码:

 * Note: The returned array must be malloced, assume caller calls free().
 */
int* nextGreaterElement(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
    
    
    int *temp=(int*)malloc(sizeof(int)*nums2Size);//先定义大点为了防止越界,最后可以用return返回真正需要的长度
    int hashmap[nums2Size][2];//为nums1的尺寸会越界,因为会碰到不出栈的情况
    int k = 0;//哈希映射下标
    int top = 0;//栈顶元素下标
    for(int i=0;i<nums2Size;i++)//遍历nums2
    {
    
    
        if(top==0)//栈为空
        {
    
    
            temp[top]=nums2[i];
            top++;
        }
        else
        {
    
    
            if(nums2[i]>temp[top-1])//满足情况1
            {
    
    
                hashmap[k][0]=temp[top-1];
                hashmap[k][1]=nums2[i];
                k++;
                top--;//出栈操作
                i--;//因为栈外大的元素不是只用一次,他可以用好多次,我们只是让栈顶元素出栈即可,栈外需要再用
            }
            else
            {
    
    
                temp[top]=nums2[i];
                top++;
            }
        }
    }
    memset(temp,-1,sizeof(int)*nums1Size);//不能直接sizeof(temp),因为temp是动态数组
    									//先都填上-1更方便
    for(int i=0;i<nums1Size;i++)//遍历nums1
    {
    
    
        int j = 0;//设立个指针来查找我们的哈希映射
        while(j<=k)//由前面可知k是有效的哈希映射数组的长度
        {
    
    
            if(nums1[i]==hashmap[j][0])
            {
    
    
                temp[i]=hashmap[j][1];
                break;
            }
            else
            {
    
    
                j++;
            }
        }
    }
    *returnSize=nums1Size;//说明一下返回的长度
    return temp;
}

猜你喜欢

转载自blog.csdn.net/xiangguang_fight/article/details/112756924