每日一题算法:2020年6月11日每日温度dailyTemperatures

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;
    }

优化的方式是由于需要多次查询链表的值,而链表的数据结构不适合查询,所以先在一次查询后将数据保存下来,可以节省几次查询的次数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值