Skip to content
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
50 changes: 4 additions & 46 deletions solution/0900-0999/0962.Maximum Width Ramp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,13 @@ tags:

### 方法一:单调栈

根据题意,我们可以发现,所有可能的 $nums[i]$ 所构成的子序列一定是单调递减的。为什么呢?我们不妨用反证法证明一下。
根据题意,我们可以发现,所有可能的 $\textit{nums}[i]$ 所构成的子序列一定是单调递减的。为什么呢?我们不妨用反证法证明一下。

假设存在 $i_1<i_2$,并且 $nums[i_1]<=nums[i_2]$,那么实际上 $nums[i_2]$一定不可能是一个候选值,因为 $nums[i_1]$ 更靠左,会是一个更优的值。因此 $nums[i]$ 所构成的子序列一定单调递减,并且 $i$ 一定是从 0 开始。
假设存在 $i_1<i_2$,并且 $\textit{nums}[i_1]\leq\textit{nums}[i_2]$,那么实际上 $\textit{nums}[i_2]$ 一定不可能是一个候选值,因为 $\textit{nums}[i_1]$ 更靠左,会是一个更优的值。因此 $\textit{nums}[i]$ 所构成的子序列一定单调递减,并且 $i$ 一定是从 0 开始。

我们用一个从栈底到栈顶单调递减的栈 $stk$ 来存储所有可能的 $nums[i]$,然后我们从右边界开始遍历 $j$,若遇到 $nums[stk.top()]<=nums[j]$,说明此时构成一个坡,循环弹出栈顶元素,更新 ans。
我们用一个从栈底到栈顶单调递减的栈 $\textit{stk}$ 来存储所有可能的 $\textit{nums}[i]$,然后我们从右边界开始遍历 $j$,若遇到 $\textit{nums}[\textit{stk.top()}]\leq\textit{nums}[j]$,说明此时构成一个坡,循环弹出栈顶元素,更新 $\textit{ans}$

时间复杂度 $O(n)$,其中 $n$ 表示 $nums$ 的长度。
时间复杂度 $O(n)$,空间复杂度 $O(n)$,其中 $n$ 表示 $\textit{nums}$ 的长度。

<!-- tabs:start -->

Expand Down Expand Up @@ -215,46 +215,4 @@ function maxWidthRamp(nums) {

<!-- solution:end -->

<!-- solution:start -->

### 方法二:排序

<!-- tabs:start -->

#### TypeScript

```ts
function maxWidthRamp(nums: number[]): number {
const idx = nums.map((x, i) => [x, i]).sort(([a], [b]) => a - b);
let [ans, j] = [0, nums.length];

for (const [_, i] of idx) {
ans = Math.max(ans, i - j);
j = Math.min(j, i);
}

return ans;
}
```

#### JavaScript

```js
function maxWidthRamp(nums) {
const idx = nums.map((x, i) => [x, i]).sort(([a], [b]) => a - b);
let [ans, j] = [0, nums.length];

for (const [_, i] of idx) {
ans = Math.max(ans, i - j);
j = Math.min(j, i);
}

return ans;
}
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- problem:end -->
52 changes: 9 additions & 43 deletions solution/0900-0999/0962.Maximum Width Ramp/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,15 @@ tags:

<!-- solution:start -->

### Solution 1: Monotonic stack
### Solution 1: Monotonic Stack

According to the problem, we can find that the subsequence formed by all possible $\textit{nums}[i]$ must be monotonically decreasing. Why is that? Let's prove it by contradiction.

Suppose there exist $i_1<i_2$ and $\textit{nums}[i_1]\leq\textit{nums}[i_2]$, then actually $\textit{nums}[i_2]$ cannot be a candidate value, because $\textit{nums}[i_1]$ is more to the left and would be a better value. Therefore, the subsequence formed by $\textit{nums}[i]$ must be monotonically decreasing, and $i$ must start from 0.

We use a monotonically decreasing stack $\textit{stk}$ (from bottom to top) to store all possible $\textit{nums}[i]$. Then we traverse $j$ starting from the right boundary. If we encounter $\textit{nums}[\textit{stk.top()}]\leq\textit{nums}[j]$, it means a ramp is formed at this point. We cyclically pop the top elements from the stack and update $\textit{ans}$.

The time complexity is $O(n)$ and the space complexity is $O(n)$, where $n$ represents the length of $\textit{nums}$.

<!-- tabs:start -->

Expand Down Expand Up @@ -203,46 +211,4 @@ function maxWidthRamp(nums) {

<!-- solution:end -->

<!-- solution:start -->

### Solution 2: Sorting

<!-- tabs:start -->

#### TypeScript

```ts
function maxWidthRamp(nums: number[]): number {
const idx = nums.map((x, i) => [x, i]).sort(([a], [b]) => a - b);
let [ans, j] = [0, nums.length];

for (const [_, i] of idx) {
ans = Math.max(ans, i - j);
j = Math.min(j, i);
}

return ans;
}
```

#### JavaScript

```js
function maxWidthRamp(nums) {
const idx = nums.map((x, i) => [x, i]).sort(([a], [b]) => a - b);
let [ans, j] = [0, nums.length];

for (const [_, i] of idx) {
ans = Math.max(ans, i - j);
j = Math.min(j, i);
}

return ans;
}
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- problem:end -->
11 changes: 0 additions & 11 deletions solution/0900-0999/0962.Maximum Width Ramp/Solution2.js

This file was deleted.

11 changes: 0 additions & 11 deletions solution/0900-0999/0962.Maximum Width Ramp/Solution2.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ tags:

最后,如果找到满足条件的矩形,返回其中面积的最小值。否则,返回 $0$。

时间复杂度 $O(n^3)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $points$ 的长度。
时间复杂度 $O(n^3)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{points}$ 的长度。

<!-- tabs:start -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,13 @@ tags:

<!-- solution:start -->

### Solution 1
### Solution 1: Hash Table + Enumeration

We use a hash table to store all the points, then enumerate three points $p_1 = (x_1, y_1)$, $p_2 = (x_2, y_2)$, $p_3 = (x_3, y_3)$, where $p_2$ and $p_3$ are the two endpoints of the diagonal of the rectangle. If the line formed by $p_1$ and $p_2$ and the line formed by $p_1$ and $p_3$ are perpendicular, and the fourth point $(x_4, y_4)=(x_2 - x_1 + x_3, y_2 - y_1 + y_3)$ exists in the hash table, then we have found a rectangle. At this point, we can calculate the area of the rectangle and update the answer.

Finally, if a rectangle that satisfies the conditions is found, return the minimum area among them. Otherwise, return $0$.

The time complexity is $O(n^3)$ and the space complexity is $O(n)$, where $n$ is the length of the array $\textit{points}$.

<!-- tabs:start -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,22 @@ The expression contains 3 operations.

<!-- solution:start -->

### Solution 1
### Solution 1: Memoization Search

We define a function $dfs(v)$, which represents the minimum number of operators needed to compose the number $v$ using $x$. Then the answer is $dfs(target)$.

The execution logic of function $dfs(v)$ is as follows:

If $x \geq v$, then we can obtain $v$ by adding $v$ instances of $x / x$, with the number of operators being $v \times 2 - 1$; or we can obtain $v$ by subtracting $(x - v)$ instances of $x / x$ from $x$, with the number of operators being $(x - v) \times 2$. We take the minimum of the two.

Otherwise, we enumerate $x^k$ starting from $k=2$ to find the first $k$ where $x^k \geq v$:

- If $x^k - v \geq v$ at this point, then we can only first obtain $x^{k-1}$, then recursively calculate $dfs(v - x^{k-1})$. The number of operators in this case is $k - 1 + dfs(v - x^{k-1})$;
- If $x^k - v < v$ at this point, then we can obtain $v$ in the above manner, with the number of operators being $k - 1 + dfs(v - x^{k-1})$; or we can first obtain $x^k$, then recursively calculate $dfs(x^k - v)$, with the number of operators being $k + dfs(x^k - v)$. We take the minimum of the two.

To avoid redundant calculations, we implement the $dfs$ function using memoization search.

The time complexity is $O(\log_{x}{target})$ and the space complexity is $O(\log_{x}{target})$.

<!-- tabs:start -->

Expand Down
Loading