leetcode596:496. Next Greater Element I(寻找元素对应位置的下一个较大值)

原题:https://leetcode.com/problems/next-greater-element-i/description/
分析:题意是有两个数组,一个数组包含另一个数组中的所有元素,设母数组为M,子数组为N,则求N中的任意一个元素在M中的对应位置之后的大于该元素的值,如果不存在,就返回-1。
Note:

All elements in nums1 and nums2 are unique.
The length of both nums1 and nums2 would not exceed 1000.

第一种方法是暴力搜索,对子数组中的每一个元素,查找在母数组中的对应元素:

vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) {
    vector<int> Next_G_ele;
    for (int item : findNums)
    {
        bool get = false,exist=false;//两个标志,一个确定是否到达该元素位置,一个确定是否存在,不存在添加-1
        for (int i = 0; i < nums.size(); i++)
        {
            if (item == nums[i])
            {
                get = true;
                continue;
            }
            if (get&&nums[i] > item)
            {
                Next_G_ele.push_back(nums[i]);
                exist = true;
                break;
            }
        }
        if (!exist)
        {
            Next_G_ele.push_back(-1);
        }
    }
    return Next_G_ele;
}

第二种方法是对前一种的改进,利用非连续存储的map结构来快速确定起始搜索位置

#include<unordered_map>//头文件
vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) {
    vector<int> Next_G_ele;
    unordered_map<int, int> map;
    for (int i = 0; i < nums.size(); i++)
        map[nums[i]] = i;//建立一个map,便于搜索每一个findNums元素对应的Nums的下标
    for (int item : findNums)
    {
        bool exist=false;
        for (int j = map[item]+1; j < nums.size(); j++)
        {
            if (nums[j] > item)
            {
                Next_G_ele.push_back(nums[j]);
                exist = true;
                break;
            }
        }
        if (!exist) Next_G_ele.push_back(-1);
    }
    return Next_G_ele;
}

第三种方法是利用栈的特性,先对母数组中的元素,每一个元素看他后面是否有大于该数的元素,再对每一个子数组中的元素进行查找,如果有,就是该数,如果没有,就是-1,通过栈与map两种数据结构来提高效率

#include<vector>
#include<unordered_map>
#include<stack>
vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) {
    vector<int> Next_G_ele;
    unordered_map<int, int> map;
    stack<int> sk;
    for (int num : nums)
    {
        while (!sk.empty() && sk.top() < num)//N{ 4, 1, 2 }, M{ 1,3,4,2 ,6}
        {
            map[sk.top()] = num;
            sk.pop();
        }
        sk.push(num);       
    }
    for (int i : findNums)
    {
        Next_G_ele.push_back(map.count(i) ? map[i] : -1 );
    }
    return Next_G_ele;
}

这种方法主要在于用栈来计算每个元素后面的较大元素,这里第一次写成了if,这样相当于只检索了后面一位元素,而用while的时候,是将每一个元素都压入栈,这样,碰到大的元素,将栈内的小于该数的元素都对应到该元素,然后将其排出,这样才能得到正确的map。

三种方法的测试代码:

int main()
{
    vector<int> N{ 4, 1, 2 }, M{ 1,3,4, 2 ,6},Next_Greater(N.size());
    Next_Greater = nextGreaterElement(N,M);
    for (int i : Next_Greater)
        cout << i << '\t';
    system("pause");
    return 0;
}

几个要点:
1、一是代码中使用的是vector的push_back方法,这里不可以指定该vector的大小,否则,前面会用0进行初始化填充。另一种思路是指定大小后,用下标来进行索引。
2、上一点提到的用下表来进行索引时,可以将所有值初始化为-1,这样只需对存在的元素进行更改。
3、map的count方法,也可以用find的迭代器返回值来代替,不知效率孰高孰低,
Next_G_ele.push_back(map.find(i)==map.cend() ? -1 : map[i])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值