2020年6月11日 08:46:59 每日温度 dailyTemperatures
默认格式:
class Solution {
public int[] dailyTemperatures(int[] T) {
}
}
解题思路;
1,暴力,遍历数组,对每个位置的元素进行循环查看后1-n项是否会大于当天的温度。
暴力算法做起来还是非常简单粗暴的。
public int[] dailyTemperatures(int[] T) {
//获取每一天的温度值
for(int i=0;i<T.length;i++){
int t=T[i];
T[i]=0;
//获取该天后面第n天的温度
for (int j=i;j<T.length;j++){
//如果比今天高,输出天数差,跳出循环
if (T[j]>t){
T[i]=j-i;
break;
}
}
}
return T;
}
2,找规律
首先想一想,暴力算法里有哪些过程是重复的,我认为读取数组中温度的过程是重复的。
首先,我们要找到数组的规律。规律在于如果第n天在m天后温度上升,则n到m天之间的区间内,天数都会小于m,因为我们记下第n天为 Tn,第m天后为T(n+m),我们可以得到Tn+1<Tn<Tm,Tn+2<Tn<Tm
根据该规则,我们修还可以进行扩展,比如我们得到Tn+1和Tn+k这一对,k<m,结合这些特性,不难想出可以使用双指针来实现功能,而且还需要使用递归的思想,递归需要两个参数,起始坐标和终点坐标,用图来演示这个过程。
1,从起始坐标0开始寻找终点左边,找到终点为1,给起点坐标设置的值为1
2,从终点坐标开始重复过程1
3,继续将终点坐标作为起始左边开始,这次获取的终点坐标
4,将起始坐标作为
。。。
感觉好像没有优化的意思,步骤都没有节省。该重复的还是重复了。思路错误。。。
3,官方解答:单调栈
在思考多时没有结果之后,我决定还是看官方的解答。
虽然之前也想过使用栈的数据结构来实现功能,但是不知道如何使用。
先了解一下什么是单调栈:
单调栈是栈的变种,就像是树和哈夫曼树那样的关系,单调栈是指栈中的元素都会按照某一规定单调递增或则递减。这里我就有第一个问题,如何将数组变成一个单调递增或者递减的栈呢?
大致的流程画图解释是这样的。
1,取出73和栈顶元素比较,栈是空的,直接把下标存进去
2,取出74和栈顶元素比较,比栈顶元素大,让栈顶元素先出栈,并且根据下标差记录天数
3,取出75和栈顶元素比较,。。。和2一样
4,取出71和栈顶元素比较,比栈顶元素小,直接加入成为新的栈顶元素
5,取出69和栈顶元素比较,和4一样
6,取出72和栈顶元素比较,比栈顶元素大,将栈顶取出,再和新的栈顶元素比较,再次替换栈顶,并且将天数取出(天数=当前下标-栈顶下标)
7,72和栈顶75比较,72小于栈顶,所以72成为新的栈顶
8,76重复以上步骤,76比下标5的72大,也比下标2的75大,所以76成为了新的栈顶,72和75都出栈
接下来就实现上述的步骤。
先写一个栈的数据结构
栈好像就是一个链表诶,只不过对读取加了限定而已
public int[] dailyTemperatures2(int[] T) {
//用List来代替栈
List<Integer> stack=new LinkedList<>();
int[] res=new int[T.length];
for(int i=0;i<T.length;){
//如果栈是空的,直接插入一个元素
if (stack.size()==0){
stack.add(i);
i++;
}
//栈顶的元素和当前元素进行比较,比当前元素大的情况
else if (T[stack.get(stack.size()-1)]>=T[i]){
stack.add(i);
i++;
}else {
//给返回数组赋值
res[stack.get(stack.size()-1)]=i-stack.get(stack.size()-1);
//移除栈顶的元素
stack.remove(stack.size()-1);
}
}
return res;
}
不是很满意啊,为什么用了官方的做法还是没能超过90%?还存在需要优化的地方吗?再研究一下。
public int[] dailyTemperatures(int[] T) {
//用List来代替栈
List<Integer> stack=new LinkedList<>();
int[] res=new int[T.length];
for(int i=0;i<T.length;){
int size=stack.size();
//如果栈是空的,直接插入一个元素
if (size==0){
stack.add(i);
i++;
continue;
}
int index=stack.get(size-1);
//栈顶的元素和当前元素进行比较,比当前元素大的情况
if (T[index]>=T[i]){
stack.add(i);
i++;
}else {
//给返回数组赋值
res[index]=i-index;
//移除栈顶的元素
stack.remove(size-1);
}
}
return res;
}
优化的方式是由于需要多次查询链表的值,而链表的数据结构不适合查询,所以先在一次查询后将数据保存下来,可以节省几次查询的次数。