[码上掘金---攒豆子|青训营主题创作文章]

118 阅读2分钟

当青训营遇上码上掘金这一两天我主要探究了攒豆子的算法题。

题目分析

该题的实质就是我们找到柱子之间的网格数。碰到这样的题,经过仔细分析,我一开始的思路是将他看作是多层的括号匹配问题。将柱子的高度看成网格层数,然后对于第一层,如果有柱子就开始计算豆子数,如果碰到另一个柱子则结束,将豆子数计入总数中,如果在给出的柱子总数n中无法匹配另一个柱子则结束。同样的依次对第二层,三层。。。n层进行遍历。这里由于从底层向上依次遍历,因此当底层左右匹配不到另一边时上层必然无法继续匹配因此可以停止。另外他也和括号匹配存在差别,因为一个柱子可以和左右两个柱子匹配,因此这里应该要用到队列。

模型方法

这里用到队列,其和括号匹配还是有所不同的。一开始我们将所有非零层数的柱子号入队列。然后出队,每一次出队的队头并与其后的柱子号相减再减一并加入到总数中,同时出队的柱子号对应的高度减一。这样当队列为空时我们便得到第一层的豆子数。然后循环,又入队减一后非零的柱子号。当入队的元素个数小于等于1时我们便可以退出,得到总数。

代码

class Solution {
public:
    int countdou(vector<int>& height) {
        int ans = 0;
        deque<int> deq;
        int n = height.size();
        int maxx=*(max_element(height.begin(), height.end()));
        int j =1;
        int fro;
    while (j<=maxx){
      for (int i=0;i<n;i++){
          if(height[i]>0)
                deq.push_back(i);
         
      }
      if(deq.size()<=1) break;
      else{while(! deq.empty()){
          fro=deq.front();
          height[fro]--;
          deq.pop_front();
          if(!deq.empty()) ans=ans+deq.front()-fro-1;
         
      }}
       j++ ;
          }
        return ans;
    }
};


分析

这个代码得到的答案是正确的,但是比较耗时,时间复杂度比较高,主要问题在于每一次都要重新入栈,同时可以看到当柱子数很多时间隔比较小时就和直接一个一个数格子没有区别。因此进行了改进想到了另外一个思路。也就是我直接换成乘法计算面积。代码思路是,我们首先遇到非零高度的柱子再入队,碰到比前一个柱子高度小直接入队,当碰到比前一个柱子大时,需要分两种情况,如果大于等于队头高度则,则依次出队,同时计算面积急出队的柱子与此时待进入的柱子的距离减一再乘以出队的柱子高度与新队头柱子高度的差。第二种是如果即将加入的柱子高度比队尾高度大但是比队头高度小,则从队尾依次出队,直到找到最后一个比他矮的柱子,同时每出去一个柱子也要计算面积,也就是用出去的柱子的高度与新队尾柱子的高度差乘以出队柱子与即将进入的柱子距离。同时需要的注意的是我们还要加上即将进入的柱子与第一个大于等于该柱子之间的豆子数量,也是用最后一个出去的柱子的高度与第一个高度大于等于即将进入柱子的队尾柱子的高度差乘以第一个高度大于等于即将进入的新柱子的队尾柱子与即将进入的柱子之间的距离。

代码

class Solution {
public:
    int trap(vector<int>& height) {
        int ans = 0;
        deque<int> deq;
        int n = height.size();
        int maxx=*(max_element(height.begin(), height.end()));
        int j =1;
        int fro;
        int minn;
        int i;
        int bac;
        for ( i=0;i<n;i++){
            if(height[i]!=0 && deq.empty())
               {deq.push_back(i);
               break;}
        }

        for ( ;i<n;i++)
        {
            if(height[i]<height[deq.back()]){
                deq.push_back(i);
            
            }
            else{
                if (height[i]>=height[deq.front()])
               {while (!deq.empty())
                {
                    fro=deq.front();
                    deq.pop_front();
                    if(!deq.empty()) ans=ans+(i-fro-1)*(height[fro]-height[deq.front()]);
                    
            }}
              else{
                  while (height[i]>height[deq.back()]){
                  bac=deq.back();
                  deq.pop_back();
                  ans=ans+(height[deq.back()]-height[bac])*(i-deq.back()-1);
                   
                  }
                  ans=ans+(height[i]-height[deq.back()])*(i-deq.back()-1);
              }
            deq.push_back(i);
        }
        }
          
        return ans;
    }
};