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 problems: No.307+ #2143

Merged
merged 1 commit into from
Dec 22, 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
feat: add solutions to lc problems: No.307+
  • Loading branch information
yanglbme committed Dec 22, 2023
commit 883562f84ec8719c36d11ec47e316c8e971292c0
2 changes: 2 additions & 0 deletions solution/0300-0399/0307.Range Sum Query - Mutable/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ numArray.sumRange(0, 2); // 返回 1 + 2 + 5 = 8
- 线段树的每个叶子节点代表一个长度为 $1$ 的元区间 $[x, x]$;
- 对于每个内部节点 $[l, r]$,它的左儿子是 $[l, mid]$,右儿子是 $[mid + 1, r]$, 其中 $mid = \lfloor \frac{l + r}{2} \rfloor$(即向下取整)。

对于本题,构造函数的时间复杂度为 $O(n \log n)$,其他操作的时间复杂度为 $O(\log n)$。空间复杂度为 $O(n)$。

<!-- tabs:start -->

### **Python3**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@

时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $prices$ 的长度。

我们注意到,状态 $f[i][]$ 的转移只与 $f[i - 1][]$ 和 $f[i - 2][0]$ 有关,因此我们可以用三个变量 $f, f_0, f_1$ 代替数组 $f$,将空间复杂度优化到 $O(1)$。
我们注意到,状态 $f[i][]$ 的转移只与 $f[i - 1][]$ 和 $f[i - 2][0]$ 有关,因此我们可以用三个变量 $f$, $f_0$, $f_1$ 代替数组 $f$,将空间复杂度优化到 $O(1)$。

<!-- tabs:start -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,34 @@

## Solutions

**Solution 1: Memoization Search**

We design a function $dfs(i, j)$, which represents the maximum profit that can be obtained starting from the $i$th day with state $j$. The values of $j$ are $0$ and $1$, respectively representing currently not holding a stock and holding a stock. The answer is $dfs(0, 0)$.

The execution logic of the function $dfs(i, j)$ is as follows:

If $i \geq n$, it means that there are no more stocks to trade, so return $0$;

Otherwise, we can choose not to trade, then $dfs(i, j) = dfs(i + 1, j)$. We can also trade stocks. If $j > 0$, it means that we currently hold a stock and can sell it, then $dfs(i, j) = prices[i] + dfs(i + 2, 0)$. If $j = 0$, it means that we currently do not hold a stock and can buy, then $dfs(i, j) = -prices[i] + dfs(i + 1, 1)$. Take the maximum value as the return value of the function $dfs(i, j)$.

The answer is $dfs(0, 0)$.

To avoid repeated calculations, we use the method of memoization search, and use an array $f$ to record the return value of $dfs(i, j)$. If $f[i][j]$ is not $-1$, it means that it has been calculated, and we can directly return $f[i][j]$.

The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $prices$.

**Solution 2: Dynamic Programming**

We can also use dynamic programming to solve this problem.

We define $f[i][j]$ to represent the maximum profit that can be obtained on the $i$th day with state $j$. The values of $j$ are $0$ and $1$, respectively representing currently not holding a stock and holding a stock. Initially, $f[0][0] = 0$, $f[0][1] = -prices[0]$.

When $i \geq 1$, if we currently do not hold a stock, then $f[i][0]$ can be obtained by transitioning from $f[i - 1][0]$ and $f[i - 1][1] + prices[i]$, i.e., $f[i][0] = \max(f[i - 1][0], f[i - 1][1] + prices[i])$. If we currently hold a stock, then $f[i][1]$ can be obtained by transitioning from $f[i - 1][1]$ and $f[i - 2][0] - prices[i]$, i.e., $f[i][1] = \max(f[i - 1][1], f[i - 2][0] - prices[i])$. The final answer is $f[n - 1][0]$.

The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $prices$.

We notice that the transition of state $f[i][]$ is only related to $f[i - 1][]$ and $f[i - 2][0]$, so we can use three variables $f$, $f_0$, $f_1$ to replace the array $f$, optimizing the space complexity to $O(1)$.

<!-- tabs:start -->

### **Python3**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@

我们可以直接按照矩阵乘法的定义,计算出结果矩阵中的每一个元素。

时间复杂度 $O(m \times n \times k)$,空间复杂度 $O(m \times n)$。
时间复杂度 $O(m \times n \times k)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是矩阵 $mat1$ 的行数和矩阵 $mat2$ 的列数,而 $k$ 是矩阵 $mat1$ 的列数或矩阵 $mat2$ 的行数。

**方法二:预处理**

我们可以预处理出两个矩阵的稀疏表示,即 $g1[i]$ 表示矩阵 $mat1$ 第 $i$ 行中所有非零元素的列下标和值,而 $g2[i]$ 表示矩阵 $mat2$ 第 $i$ 行中所有非零元素的列下标和值。

接下来,我们遍历每一行 $i$,遍历 $g1[i]$ 中的每一个元素 $(k, x)$,遍历 $g2[k]$ 中的每一个元素 $(j, y)$,那么最终 $mat1[i][k] \times mat2[k][j]$ 就会对应到结果矩阵中的 $ans[i][j]$,我们将所有的结果累加即可。

时间复杂度 $O(m \times n \times k)$,空间复杂度 $O(m \times n)$。
时间复杂度 $O(m \times n \times k)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是矩阵 $mat1$ 的行数和矩阵 $mat2$ 的列数,而 $k$ 是矩阵 $mat1$ 的列数或矩阵 $mat2$ 的行数。

<!-- tabs:start -->

Expand Down
14 changes: 14 additions & 0 deletions solution/0300-0399/0311.Sparse Matrix Multiplication/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@

## Solutions

**Solution 1: Direct Multiplication**

We can directly calculate each element in the result matrix according to the definition of matrix multiplication.

The time complexity is $O(m \times n \times k)$, and the space complexity is $O(m \times n)$. Where $m$ and $n$ are the number of rows of matrix $mat1$ and the number of columns of matrix $mat2$ respectively, and $k$ is the number of columns of matrix $mat1$ or the number of rows of matrix $mat2$.

**Solution 2: Preprocessing**

We can preprocess the sparse representation of the two matrices, i.e., $g1[i]$ represents the column index and value of all non-zero elements in the $i$th row of matrix $mat1$, and $g2[i]$ represents the column index and value of all non-zero elements in the $i$th row of matrix $mat2$.

Next, we traverse each row $i$, traverse each element $(k, x)$ in $g1[i]$, traverse each element $(j, y)$ in $g2[k]$, then $mat1[i][k] \times mat2[k][j]$ will correspond to $ans[i][j]$ in the result matrix, and we can accumulate all the results.

The time complexity is $O(m \times n \times k)$, and the space complexity is $O(m \times n)$. Where $m$ and $n$ are the number of rows of matrix $mat1$ and the number of columns of matrix $mat2$ respectively, and $k$ is the number of columns of matrix $mat1$ or the number of rows of matrix $mat2$.

<!-- tabs:start -->

### **Python3**
Expand Down
10 changes: 9 additions & 1 deletion solution/0300-0399/0313.Super Ugly Number/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,15 @@

## Solutions

Priority Queue.
**Solution 1: Priority Queue (Min Heap)**

We use a priority queue (min heap) to maintain all possible super ugly numbers, initially putting $1$ into the queue.

Each time we take the smallest super ugly number $x$ from the queue, multiply $x$ by each number in the array `primes`, and put the product into the queue. Repeat the above operation $n$ times to get the $n$th super ugly number.

Since the problem guarantees that the $n$th super ugly number is within the range of a 32-bit signed integer, before we put the product into the queue, we can first check whether the product exceeds $2^{31} - 1$. If it does, there is no need to put the product into the queue. In addition, the Euler sieve can be used for optimization.

The time complexity is $O(n \times m \times \log (n \times m))$, and the space complexity is $O(n \times m)$. Where $m$ and $n$ are the length of the array `primes` and the given integer $n$ respectively.

<!-- tabs:start -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@

## Solutions

**Solution 1: DFS**

DFS traverses the binary tree, recording the value, depth, and horizontal offset of each node. Then sort all nodes by horizontal offset from small to large, then by depth from small to large, and finally group by horizontal offset.

The time complexity is $O(n\log \log n)$, and the space complexity is $O(n)$. Where $n$ is the number of nodes in the binary tree.

**Solution 2: BFS**

A better approach to this problem should be BFS, traversing from top to bottom level by level.

The time complexity is $O(n\log n)$, and the space complexity is $O(n)$. Where $n$ is the number of nodes in the binary tree.

<!-- tabs:start -->

### **Python3**
Expand Down
2 changes: 1 addition & 1 deletion solution/0300-0399/0316.Remove Duplicate Letters/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@

最后将栈中元素拼接成字符串作为结果返回。

时间复杂度 $O(n)$。其中 $n$ 为字符串 $s$ 的长度。
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $s$ 的长度。

<!-- tabs:start -->

Expand Down
10 changes: 9 additions & 1 deletion solution/0300-0399/0316.Remove Duplicate Letters/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,15 @@

## Solutions

**Stack**
**Solution 1: Stack**

We use an array `last` to record the last occurrence of each character, a stack to save the result string, and an array `vis` or an integer variable `mask` to record whether the current character is in the stack.

Traverse the string $s$, for each character $c$, if $c$ is not in the stack, we need to check whether the top element of the stack is greater than $c$. If it is greater than $c$ and the top element of the stack will appear later, we pop the top element of the stack and push $c$ into the stack.

Finally, concatenate the elements in the stack into a string and return it as the result.

The time complexity is $O(n)$, and the space complexity is $O(n)$. Where $n$ is the length of the string $s$.

<!-- tabs:start -->

Expand Down