设计一个算法收集某些股票的每日报价,并返回该股票当日价格的 跨度 。
当日股票价格的 跨度 被定义为股票价格小于或等于今天价格的最大连续日数(从今天开始往回数,包括今天)。
- 例如,如果未来 7 天股票的价格是 
[100,80,60,70,60,75,85],那么股票跨度将是 [1,1,1,2,1,4,6] 。 
实现 StockSpanner 类:
StockSpanner() 初始化类对象。 
int next(int price) 给出今天的股价 price ,返回该股票当日价格的 跨度 。 
示例:
**输入** :
["StockSpanner", "next", "next", "next", "next", "next", "next", "next"]
[[], [100], [80], [60], [70], [60], [75], [85]]
**输出** :
[null, 1, 1, 1, 2, 1, 4, 6]
**解释:**
StockSpanner stockSpanner = new StockSpanner();
stockSpanner.next(100); // 返回 1
stockSpanner.next(80);  // 返回 1
stockSpanner.next(60);  // 返回 1
stockSpanner.next(70);  // 返回 2
stockSpanner.next(60);  // 返回 1
stockSpanner.next(75);  // 返回 4 ,因为截至今天的最后 4 个股价 (包括今天的股价 75) 都小于或等于今天的股价。
stockSpanner.next(85);  // 返回 6
提示:
1 <= price <= 105 
- 最多调用 
next 方法 104 次 
方法一:单调栈
思路
调用 next 时,输入是新的一天的股票价格,需要返回包含此日在内的,往前数最多有连续多少日的股票价格是小于等于今日股票价格的。如果把每日的 price 当成数组不同下标的值,即需要求出每个值与上一个更大元素之间的下标之差。这种题目可以用单调栈求解,具体原理可以参考「496. 下一个更大元素 I 的官方题解的方法二 」。此题的具体解法上,栈的元素可以是股票价格的下标(即天数)和股票价格的二元数对,并且在栈中先插入一个最大值作为天数为 -1 天的价格,来保证栈不会为空。调用 next 时,先将栈中价格小于等于此时 price 的元素都弹出,直到遇到一个大于 price 的值,并将 price 入栈,计算下标差返回。
代码
[sol1-Python3]1 2 3 4 5 6 7 8 9 10 11
   | class StockSpanner:     def __init__(self):         self.stack = [(-1, inf)]         self.idx = -1
      def next(self, price: int) -> int:         self.idx += 1         while price >= self.stack[-1][1]:             self.stack.pop()         self.stack.append((self.idx, price))         return self.idx - self.stack[-2][0]
   | 
  
[sol1-Java]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
   | class StockSpanner {     Deque<int[]> stack;     int idx;
      public StockSpanner() {         stack = new ArrayDeque<int[]>();         stack.push(new int[]{-1, Integer.MAX_VALUE});         idx = -1;     }
      public int next(int price) {         idx++;         while (price >= stack.peek()[1]) {             stack.pop();         }         int ret = idx - stack.peek()[0];         stack.push(new int[]{idx, price});         return ret;     } }
  | 
  
[sol1-C#]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
   | public class StockSpanner {     Stack<Tuple<int, int>> stack;     int idx;
      public StockSpanner() {         stack = new Stack<Tuple<int, int>>();         stack.Push(new Tuple<int, int>(-1, int.MaxValue));         idx = -1;     }
      public int Next(int price) {         idx++;         while (price >= stack.Peek().Item2) {             stack.Pop();         }         int ret = idx - stack.Peek().Item1;         stack.Push(new Tuple<int, int>(idx, price));         return ret;     } }
  | 
  
[sol1-C++]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
   | class StockSpanner { public:     StockSpanner() {         this->stk.emplace(-1, INT_MAX);         this->idx = -1;     }          int next(int price) {         idx++;         while (price >= stk.top().second) {             stk.pop();         }         int ret = idx - stk.top().first;         stk.emplace(idx, price);         return ret;     }
  private:     stack<pair<int, int>> stk;      int idx; };
  | 
  
[sol1-C]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
   | typedef struct Node {     int first;     int second;     struct Node *next; } Node;
  typedef struct {     Node *stack;     int idx; } StockSpanner;
  Node* nodeCreate(int first, int second) {     Node *obj = (Node *)malloc(sizeof(Node));     obj->first = first;     obj->second = second;     obj->next = NULL;        return obj;  }
  StockSpanner* stockSpannerCreate() {     StockSpanner *obj = (StockSpanner *)malloc(sizeof(StockSpanner));     obj->idx = -1;     obj->stack = nodeCreate(-1, INT_MAX);     return obj; }
  int stockSpannerNext(StockSpanner* obj, int price) {     obj->idx++;     while (price >= obj->stack->second) {         Node *p = obj->stack;         obj->stack = obj->stack->next;         free(p);     }     int ret = obj->idx - obj->stack->first;     Node *p = nodeCreate(obj->idx, price);     p->next = obj->stack;     obj->stack = p;     return ret; }
  void stockSpannerFree(StockSpanner* obj) {     for (Node *p = obj->stack; p;) {         Node *node = p;         p = p->next;         free(node);     }     free(obj); }
  | 
  
[sol1-JavaScript]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   | var StockSpanner = function() {     this.stack = [];     this.stack.push([-1, Number.MAX_VALUE]);     this.idx = -1; };
  StockSpanner.prototype.next = function(price) {     this.idx++;     while (price >= this.stack[this.stack.length - 1][1]) {         this.stack.pop();     }     let ret = this.idx - this.stack[this.stack.length - 1][0];     this.stack.push([this.idx, price]);     return ret; };
  | 
  
[sol1-Golang]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | type StockSpanner struct {     stack [][2]int     idx   int }
  func Constructor() StockSpanner {     return StockSpanner{[][2]int{{-1, math.MaxInt32}}, -1} }
  func (s *StockSpanner) Next(price int) int {     s.idx++     for price >= s.stack[len(s.stack)-1][1] {         s.stack = s.stack[:len(s.stack)-1]     }     s.stack = append(s.stack, [2]int{s.idx, price})     return s.idx - s.stack[len(s.stack)-2][0] }
  | 
  
复杂度分析