Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add solutions to lc problem: No.0901 #1754

Merged
merged 1 commit into from
Oct 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions solution/0900-0999/0901.Online Stock Span/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,17 @@ stockSpanner.next(85); // 返回 6

**方法一:单调栈**

根据题目描述,我们可以知道,对于当日价格 `price`,从这个价格开始往前找,找到第一个比这个价格大的价格,这两个价格的下标差 `cnt` 就是当日价格的跨度。
根据题目描述,我们可以知道,对于当日价格 $price$,从这个价格开始往前找,找到第一个比这个价格大的价格,这两个价格的下标差 $cnt$ 就是当日价格的跨度。

这实际上是经典的单调栈模型,找出左侧第一个比当前元素大的元素。

我们维护一个从栈底到栈顶价格单调递减的栈,栈中每个元素存放的是 `(price, cnt)` 数据对,其中 `price` 表示价格,`cnt` 表示当前价格的跨度。
我们维护一个从栈底到栈顶价格单调递减的栈,栈中每个元素存放的是 $(price, cnt)$ 数据对,其中 $price$ 表示价格,而 $cnt$ 表示当前价格的跨度。

出现价格 `price` 时,我们将其与栈顶元素进行比较,如果栈顶元素的价格小于等于 `price`,则将当日价格的跨度 `cnt` 加上栈顶元素的跨度,然后将栈顶元素出栈,直到栈顶元素的价格大于 `price`,或者栈为空为止。
出现价格 $price$ 时,我们将其与栈顶元素进行比较,如果栈顶元素的价格小于等于 $price$,则将当日价格的跨度 $cnt$ 加上栈顶元素的跨度,然后将栈顶元素出栈,直到栈顶元素的价格大于 $price$,或者栈为空为止。

最后将 `(price, cnt)` 入栈,返回 `cnt` 即可。
最后将 $(price, cnt)$ 入栈,返回 $cnt$ 即可。

时间复杂度 $O(n)$,其中 $n$ 为 `next` 函数的调用次数。
时间复杂度 $O(n)$,其中 $n$ 为 $next$ 函数的调用次数。

<!-- tabs:start -->

Expand Down Expand Up @@ -138,7 +138,7 @@ public:
cnt += stk.top().second;
stk.pop();
}
stk.push({price, cnt});
stk.emplace(price, cnt);
return cnt;
}

Expand Down Expand Up @@ -187,19 +187,19 @@ type pair struct{ price, cnt int }

```ts
class StockSpanner {
private stack: [number, number][];
private stk: number[][];

constructor() {
this.stack = [[Infinity, -1]];
this.stk = [];
}

next(price: number): number {
let res = 1;
while (this.stack[this.stack.length - 1][0] <= price) {
res += this.stack.pop()[1];
let cnt = 1;
while (this.stk.length && this.stk.at(-1)[0] <= price) {
cnt += this.stk.pop()[1];
}
this.stack.push([price, res]);
return res;
this.stk.push([price, cnt]);
return cnt;
}
}

Expand All @@ -215,7 +215,7 @@ class StockSpanner {
```rust
use std::collections::VecDeque;
struct StockSpanner {
stack: VecDeque<(i32, i32)>,
stk: VecDeque<(i32, i32)>,
}


Expand All @@ -226,17 +226,17 @@ struct StockSpanner {
impl StockSpanner {
fn new() -> Self {
Self {
stack: vec![(i32::MAX, -1)].into_iter().collect()
stk: vec![(i32::MAX, -1)].into_iter().collect()
}
}

fn next(&mut self, price: i32) -> i32 {
let mut res = 1;
while self.stack.back().unwrap().0 <= price {
res += self.stack.pop_back().unwrap().1;
let mut cnt = 1;
while self.stk.back().unwrap().0 <= price {
cnt += self.stk.pop_back().unwrap().1;
}
self.stack.push_back((price, res));
res
self.stk.push_back((price, cnt));
cnt
}
}

Expand Down
44 changes: 29 additions & 15 deletions solution/0900-0999/0901.Online Stock Span/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@ stockSpanner.next(85); // return 6

## Solutions

**Solution 1: Monotonic Stack**

According to the problem description, we can know that for the price price on a certain day, we need to find the first price that is greater than price when looking back, and the difference between the indices of these two prices is the span of the price on that day.

This is actually a classic monotonic stack model, which finds the first element on the left that is greater than the current element.

We maintain a stack that is monotonically decreasing from the bottom to the top in terms of prices. Each element in the stack stores a pair of $(price, cnt)$, where $price$ represents the price, and $cnt$ represents the span of the current price.

When encountering a price $price$, we compare it with the top element of the stack. If the price of the top element of the stack is less than or equal to price, we add the span cnt of the current price to the span of the top element of the stack, and then pop the top element of the stack until the price of the top element of the stack is greater than price, or the stack is empty.

Finally, we push $(price, cnt)$ onto the stack and return $cnt$.

The time complexity is $O(n)$, where $n$ is the number of calls to the next function.

<!-- tabs:start -->

### **Python3**
Expand Down Expand Up @@ -113,7 +127,7 @@ public:
cnt += stk.top().second;
stk.pop();
}
stk.push({price, cnt});
stk.emplace(price, cnt);
return cnt;
}

Expand Down Expand Up @@ -162,19 +176,19 @@ type pair struct{ price, cnt int }

```ts
class StockSpanner {
private stack: [number, number][];
private stk: number[][];

constructor() {
this.stack = [[Infinity, -1]];
this.stk = [];
}

next(price: number): number {
let res = 1;
while (this.stack[this.stack.length - 1][0] <= price) {
res += this.stack.pop()[1];
let cnt = 1;
while (this.stk.length && this.stk.at(-1)[0] <= price) {
cnt += this.stk.pop()[1];
}
this.stack.push([price, res]);
return res;
this.stk.push([price, cnt]);
return cnt;
}
}

Expand All @@ -190,7 +204,7 @@ class StockSpanner {
```rust
use std::collections::VecDeque;
struct StockSpanner {
stack: VecDeque<(i32, i32)>,
stk: VecDeque<(i32, i32)>,
}


Expand All @@ -201,17 +215,17 @@ struct StockSpanner {
impl StockSpanner {
fn new() -> Self {
Self {
stack: vec![(i32::MAX, -1)].into_iter().collect()
stk: vec![(i32::MAX, -1)].into_iter().collect()
}
}

fn next(&mut self, price: i32) -> i32 {
let mut res = 1;
while self.stack.back().unwrap().0 <= price {
res += self.stack.pop_back().unwrap().1;
let mut cnt = 1;
while self.stk.back().unwrap().0 <= price {
cnt += self.stk.pop_back().unwrap().1;
}
self.stack.push_back((price, res));
res
self.stk.push_back((price, cnt));
cnt
}
}

Expand Down
2 changes: 1 addition & 1 deletion solution/0900-0999/0901.Online Stock Span/Solution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class StockSpanner {
cnt += stk.top().second;
stk.pop();
}
stk.push({price, cnt});
stk.emplace(price, cnt);
return cnt;
}

Expand Down
14 changes: 7 additions & 7 deletions solution/0900-0999/0901.Online Stock Span/Solution.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::VecDeque;
struct StockSpanner {
stack: VecDeque<(i32, i32)>,
stk: VecDeque<(i32, i32)>,
}


Expand All @@ -11,17 +11,17 @@ struct StockSpanner {
impl StockSpanner {
fn new() -> Self {
Self {
stack: vec![(i32::MAX, -1)].into_iter().collect()
stk: vec![(i32::MAX, -1)].into_iter().collect()
}
}

fn next(&mut self, price: i32) -> i32 {
let mut res = 1;
while self.stack.back().unwrap().0 <= price {
res += self.stack.pop_back().unwrap().1;
let mut cnt = 1;
while self.stk.back().unwrap().0 <= price {
cnt += self.stk.pop_back().unwrap().1;
}
self.stack.push_back((price, res));
res
self.stk.push_back((price, cnt));
cnt
}
}

Expand Down
14 changes: 7 additions & 7 deletions solution/0900-0999/0901.Online Stock Span/Solution.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
class StockSpanner {
private stack: [number, number][];
private stk: number[][];

constructor() {
this.stack = [[Infinity, -1]];
this.stk = [];
}

next(price: number): number {
let res = 1;
while (this.stack[this.stack.length - 1][0] <= price) {
res += this.stack.pop()[1];
let cnt = 1;
while (this.stk.length && this.stk.at(-1)[0] <= price) {
cnt += this.stk.pop()[1];
}
this.stack.push([price, res]);
return res;
this.stk.push([price, cnt]);
return cnt;
}
}

Expand Down