数据结构与算法---栈---每日温度

每日温度

739.每日温度

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

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

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


思路1:利用栈

该题其实是利用栈寻找左右第一个比它大的数的一个变种

其实,题目就是想求右边某一元素a的右边,第一个比a大的元素b距离a的距离
这不就是,找出右边第一个比它大的值一样么

class Solution {
    public int[] dailyTemperatures(int[] T) {
        //先写边界值
		if(T == null || T.length == 0) return null;
		
		//数组里面放索引
		int[] rightArray = new int[T.length];
		
		//保持栈,从栈底到栈顶是单调递减的
		Stack<Integer> stack = new Stack<Integer>();
		
		//扫描一遍数组
		for(int i = 0; i < T.length; i++)
		{
            //> 而非 >=
			while (!stack.empty() && T[i] > T[stack.peek()])
			{
				rightArray[stack.peek()] = i - stack.peek();
                stack.pop();
			}
			stack.push(i);
		}
		return rightArray;
    }
}

思路2:倒推法

该思路属于动态规划
由已知,推出未知

首先可以确定的是,最后一个元素的天数肯定为0,因为,后面已经没有了。

然后再看倒数第二个
如果倒数第二个的值,比倒数第一个的值大,则倒数第二个值的天数是0
如果倒数第二个的值,比倒数第一个的值小,则倒数第二个值的天数是1

依次类推

换成伪代码是:
i用来扫描所有的元素,从右往左扫描(i逐渐递减),一开始i指向倒数第2个元素
对于每一个j,一开始令j = i + 1;

  1. 如果T[i] < T[j],那么values[i] = j - i,然后i --;
  2. T[i] == T[j]
    2.1 如果values[j] = 0;那么,values[i] = 0,然后i --;
    2.2 如果values[j] != 0;那么,values[i] = values[j] + j - i,然后i --;
  3. 如果T[i] > T[j]
    3.1 如果values[j] = 0;那么,values[i] = 0,然后i --;
    3.2 如果values[j] != 0;那么,j = j + values[j],然后重新进入第一步;
class Solution {
    public int[] dailyTemperatures(int[] T) {
        //先写边界值
		if(T == null || T.length == 0) return null;
		
		int[] valuesArray = new int[T.length];

        valuesArray[T.length - 1] = 0;
		
        for(int i = T.length - 2; i >= 0; i--)
        {
            int j = i + 1;
            while(true){
                if(T[i] < T[j]){
                    valuesArray[i] = j - i;
                    break;
                }else if(T[i] == T[j]){
                    if(valuesArray[j] == 0){
                        valuesArray[i] = 0;
                     }else{
                        //相等,但是两个不一样挨着,所以必须j - i
                        valuesArray[i] = valuesArray[j] + j - i;
                    }
                    break;
                }else{//T[i] > T[j]
                    if(valuesArray[j] == 0){
                        valuesArray[i] = 0;
                        break;
                    }else{
                        j = j + valuesArray[j];
                    }
                }
            }
        }
		return valuesArray;
    }
}

需要注意的地方:
虽然在定义的时候,int j = i + 1;
但是,在所有求i与j的距离的时候,不能直接使用1
必须使用j - i,这是因为,有可能是3.2的情况,j已经变了

另外,由于3.2需要进行循环,所以从1开始,就是一个循环
巧妙运用break,结束循环,使得在正常情况下循环只执行一次,而只有在3.2的时候循环才执行

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值