每日温度——java实现

题目

根据每日 气温 列表,请重新生成一个列表,对应位置的输入是你需要再等待多久温度才会升高超过该日的天数。如果之后都不会升高,请在该位置用 0 来代替。例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。

算法

1、依次遍历

思想:依次从该判断位置后面的一位往后遍历到数组末尾进行比较,如果中甲找到目标值,则返回,否则遍历到数组末尾

public int[] dailyTemperatures(int[] T) {
  int size=T.length;
  int k=0;
  int[] arr=new int[size];
  while(k<size) {
   int temp=T[k];
   int n=0;
  for(int i=k+1;i<size;i++) {
   if(temp<T[i]) {
    arr[k]=n+1;
    break;
   }else {  //当不存在比该温度高得情况时
    n+=1;
    if(n==size-k) {  //当遍历到最后一个温度仍没有找到高于该温度的温度时,返回0
      arr[i]=0;
    }
   }
  }
  k++;
   }
  return arr;
    }
第一次精简
else {
    n+=1;
    if(n==size-k) {
      arr[i]=0;
    }
   }

将else条件判断删除运行时间缩短一半,因为这个判断纯属多余。因为arr[]数组初始化就是0,找不到直接返回就可以了,不用再用一个条件语句判断将其置0。修改后得代码如下

public int[] dailyTemperatures(int[] T) { 
       int size=T.length;
       int[] arr=new int[size];        
       for(int k=0;k<size;k++) {           //将while语句换成for语句 
            int temp=T[k];           
            int n=0;        
            for(int i=k+1;i<size;i++) {            
                 if(temp<T[i]) {    
                    arr[k]=n+1;               
                     break;            
                     }            
                     n++;      
               }     
        }      
   return arr;
     }

注意:1、删除一个条件判断分支else语句后,运行时间缩短一半
2将while循环换成for循环后,时间缩短100多ms,具体原因不清楚,百度到的答案也说while循环和for循环得执行效率不相上下,执行效率主要取决于循环次数,甚至while循环得执行效率腰稍好于for循环。能用for循环时尽量用for循环

2、栈实现

运行时间84ms

思想:栈中存储的是数组中元素对应的索引值,其对应的元素值是依次递增的,遍历时采用反向遍历的方法,从后往前依次过滤掉无效的值。每次新的元素入栈时,栈顶值就是第一个大于该元素的元素索引值,只需要将栈顶元素索引值减去新元素索引值就是当前位置的arr[i]。
用数组 [73, 74, 75, 71, 69, 72, 76, 73]举例如下,为方便理解,将栈中索引值对应的元素值用()写在旁边:
i=7,stack(7,(73)),arr[i]=0;
i=6,stack(6,(76)),arr[i]=0;
//因为新元素76>73,为保证栈中索引对应的元素值递增性,应该先把栈顶元素弹出再将新元素压入栈*

i=5,stack(5(72)6(76)),arr[i]=栈顶索引值6-当前索引值i=6-5=1;
//因为新元素72<73,符合栈中索引对应的元素值递增性,先进行计算arr[i]的值,再将新元素压入栈
i=4,stack(4(69),5(72)6(76)), arr[i]=5-i=1;
i=3,stack(3(71),5,72),6,(76)),arr[i]=5-i=2;
i=2,stack(2(75)6(76)), arr[i]=6-i=4;
i=1,stack(1(74) 2(75)6(76)), arr[i]=2-1=1;
i=0,stack(0(73) 1(74) 2(75)6(76)), arr[i]=1-0=1;

public int[] dailyTemperatures(int[] T) {
  Stack<Integer> s=new Stack<>(); // 用于记录遇到的每个递增值得索引值
  int size=T.length;
  int[] arr=new int[size];       //初始化返回的数组
  for(int i=size-1;i>=0;i--) { //反向遍历
    while(!s.empty()&&T[i]>=T[s.peek()]) {//当前值大于栈顶值时,把栈顶的索引值弹出,
                                       //直到能够保证栈中的元素是递增的
     s.pop();
    }
    if(!s.empty()) {                     //当栈中的元素全部弹出时,说明
     arr[i]=s.peek()-i;
    }
   /*
    * if(s.empty()) { arr[i]=0; }else { arr[i]=s.peek()-i; }
    */
    s.push(i);                         //将值仅次于栈顶索引值对应的数的索引值压入栈
  }
  return arr;                                
 }
3、反向遍历实现

用时4ms
思想:反向求出每个元素对应的温度升高需要等待的天数,以数组T=[73, 74, 75, 71, 69, 72, 76, 73]为例:
1、i=7:T[i]73对应的arr[7]=0;
2、i=6:T[i]先跟T[i+1]比较,76>73,而没有再出现比73还大的数,所以arr[6]=0;
3、i=5:T[i]先跟T[i+1]比较,72<76,故arr[5]=1;
4、i=4:T[i]先跟T[i+1]比较,69<72,故arr[4]=1;

5、i=3:T[i]先跟T[i+1]比较,71>69,先定位到第一个比T[i+1]69大的数(因为大于69的数不一定大于71,但第一个大于69的数之前的数都是小于等于69的数,则一定小于71),69对应的索引值为4,则第一个比69大的数的索引值为:4+arr[4]=5,该索引值对应的数是72,71<72,所以arr[3]=5-3=2;

6、i=2:T[i]先跟T[i+1]比较,75>71,71的索引值为3,先定位到第一个大于71的数的位置为:3+arr[3]=5,该值为72,72<75,接着往下找出第一个大于72的值的位置为:5+arr[5]=6,该处的值为76,76>75,即arr[i]=6-i=4;

7、i=1:T[i]先跟T[i+1]比较,74<75,故arr[i]=1;
8、i=0:T[i]先跟T[i+1]比较,73<74,故arr[i]=1;

int size=T.length;
  int[] arr=new int[size];
  for(int i=size-2;i>=0;i--) {
   for(int j=i+1;j<size;j+=arr[j]) { //直接定位到下一个大于T[j]的位置为j
     if(T[i]<T[j]) {
     arr[i]=j-i;
     break;
       }
     if(arr[j]==0) { //当arr[j]=0时,即没有比T[j]大的数了
      if(T[j]>T[i]) {//如果刚好这时T[j]>T[i]
       arr[i]=j-i;
      }
       break;        //如果到这儿都还没有找到大于T[i]的数,则不存在这个数,跳出循环
       }
   }
  }
  return arr;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值