力扣739. 每日温度--暴力法与单调栈

739. 每日温度

请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。

例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。

提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 
[30, 100] 范围内的整数。

方法一:初始暴力法(超时)

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* dailyTemperatures(int* T, int TSize, int* returnSize){
    
    
    int *a = (int*)malloc(sizeof(int)*TSize);
    for(int i=0;i<TSize;i++)
    {
    
    
        int sum = 0;
        for(int j=i;j<TSize;j++)
        {
    
    
            if(T[j]>T[i])
            {
    
    
                a[i]=sum;
                break;
            }
            if(j==TSize-1)
            {
    
    
                a[i]=0;
            }
            else
            {
    
    
                sum++;
            }
        }


    }
    *returnSize=TSize;
    return a;
}

方法二:优化后暴力法

因为最后一个元素直接返回0即可。

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* dailyTemperatures(int* T, int TSize, int* returnSize){
    
    
    int *a = (int*)malloc(sizeof(int)*TSize);
    for(int i=0;i<TSize-1;i++)
    {
    
    
        int sum = 1;
        for(int j=i+1;j<TSize;j++)
        {
    
    
            if(T[j]>T[i])
            {
    
    
                a[i]=sum;
                break;
            }
            if(j==TSize-1)
            {
    
    
                a[i]=0;
            }
            else
            {
    
    
                sum++;
            }
        }
    }
    a[TSize-1]=0;
    *returnSize=TSize;
    return a;
}

方法三:单调栈

先附上力扣题解里一个大神的小视频:

力扣程序员吴师兄所做视频

我们可以建造两个动态数组来模拟栈。

设立temp数组来存储每次温度对应的原数组里的下标,res数组来存储我们真正要的答案

我们之所以用temp数组来存储温度对应原数组的下标是因为这样的话由于存储下标可以很快找到下标,且由于下标知道,我们也能很快的从温度数组中找到他对应的温度,只需温度数组下标中嵌套temp数组即可。

因为由题可知,一旦出现“气温在这之后都不再升高”,则此时应给res赋值为0,所以为了避免麻烦我们可以开始就将整个数组都初始化为0,这样后面不用再进行赋值操作了。
从动画可知我们利用两个数组来模拟的是入栈和出栈。

即:
当栈内为空时,我们需要将temp数组导入栈中,即直接入栈;当栈不为空时,我们需要考虑两种情况:
1.若此时对应的温度大于栈内存储的温度。即此时栈外的要进入栈的元素大于栈顶的元素。
则此时可以将栈顶的元素出栈,并计算二者在温度数组中的下标差,赋值给res数组中,接着比较栈顶下面的元素与栈外的要进入栈的元素。若满足大于,则继续出栈及相同赋值操作,直到栈内没有元素为止。
若小于则不出栈了,让栈外的进栈。
2.若不大于,则其直接入栈。

因此代码如下:

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* dailyTemperatures(int* T, int TSize, int* returnSize){
    
    
    int *temp = (int*)malloc(sizeof(int)*TSize);
    memset(temp,0,sizeof(int)*TSize);
    int *res = (int*)malloc(sizeof(int)*TSize);
    memset(res,0,sizeof(int)*TSize);
    int index = -1;//此为代表栈内元素的下标
    for(int i=0;i<TSize;i++)
    {
    
    
        while(index>=0&&T[i]>T[temp[index]])//满足情况一时
        {
    
    
            res[temp[index]]=i-temp[index];
            index--;//index--其实模拟了出栈并且也成功让栈顶紧挨着的下面的元素进行下一轮的比较。
            //因为栈中下标提前了,所以在赋值时会出现覆盖的情况,即模拟了出栈
        }
        index++;//要入栈,所以要更新一下栈内下标
        temp[index]=i;//入栈操作,也是借助“覆盖”操作对一些元素完成出栈
    }
    *returnSize=TSize;
    return res;
}

且对于“*returnSize=TSize”:
因为你返回了指针,但是需要告诉外部,指针指向内存的长度。这就是returnSize的用处。

猜你喜欢

转载自blog.csdn.net/xiangguang_fight/article/details/112581646
今日推荐