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.2951~2954 #2060

Merged
merged 1 commit into from
Dec 4, 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
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@

把每一行所有可能的状态进行分类。根据对称性原理,当一行只有 $3$ 个元素时,所有合法状态分类为:$010$ 型, $012$ 型。

- 当状态为 $010$ 型时:下一行可能的状态为$101$, $102$, $121$, $201$, $202$。这 $5$ 个状态可归纳为 $3$ 个 $010$ 型,$2$ 个 $012$ 型。
- 当状态为 $012$ 型时:下一行可能的状态为$101$, $120$, $121$, $201$。这 $4$ 个状态可归纳为 $2$ 个 $010$ 型,$2$ 个 $012$ 型。
- 当状态为 $010$ 型时:下一行可能的状态为 $101$, $102$, $121$, $201$, $202$。这 $5$ 个状态可归纳为 $3$ 个 $010$ 型,以及 $2$ 个 $012$ 型。
- 当状态为 $012$ 型时:下一行可能的状态为 $101$, $120$, $121$, $201$。这 $4$ 个状态可归纳为 $2$ 个 $010$ 型,以及 $2$ 个 $012$ 型。

综上所述,可以得到$newf0 = 3 \times f0 + 2 \times f1$, $newf1 = 2 \times f0 + 2 \times f1$。
综上所述,可以得到 $newf0 = 3 \times f0 + 2 \times f1$, $newf1 = 2 \times f0 + 2 \times f1$。

时间复杂度 $O(n)$,其中 $n$ 是网格的行数。空间复杂度 $O(1)$。

Expand All @@ -85,7 +85,7 @@ $$

最终的答案即为 $f[n][j]$ 的总和,其中 $j$ 是任意合法的状态。

我们注意到$f[i][j]$ 只和 $f[i - 1][k]$ 有关,因此我们可以使用滚动数组优化空间复杂度。
我们注意到 $f[i][j]$ 只和 $f[i - 1][k]$ 有关,因此我们可以使用滚动数组优化空间复杂度。

时间复杂度 $O((m + n) \times 3^{2m})$,空间复杂度 $O(3^m)$。其中 $n$ 和 $m$ 分别是网格的行数和列数。

Expand Down
8 changes: 8 additions & 0 deletions solution/2900-2999/2951.Find the Peaks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ mountain[2] 也不可能是峰值,因为它不严格大于 mountain[3] 和 mou

<!-- 这里可写通用的实现逻辑 -->

**方法一:直接遍历**

我们直接遍历下标 $i \in [1, n-2]$,对于每个下标 $i$,如果满足 $mountain[i-1] < mountain[i]$ 并且 $mountain[i + 1] < mountain[i]$,那么 $mountain[i]$ 就是一个峰值,我们将下标 $i$ 加入答案数组中。

遍历结束后,返回答案数组即可。

时间复杂度 $O(n)$,其中 $n$ 是数组的长度。忽略答案数组的空间消耗,空间复杂度 $O(1)$。

<!-- tabs:start -->

### **Python3**
Expand Down
8 changes: 8 additions & 0 deletions solution/2900-2999/2951.Find the Peaks/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ So the answer is [1,3].

## Solutions

**Solution 1: Direct Traversal**

We directly traverse the index $i \in [1, n-2]$. For each index $i$, if $mountain[i-1] < mountain[i]$ and $mountain[i + 1] < mountain[i]$, then $mountain[i]$ is a peak, and we add index $i$ to the answer array.

After the traversal ends, we return the answer array.

The time complexity is $O(n)$, where $n$ is the length of the array. Ignoring the space consumption of the answer array, the space complexity is $O(1)$.

<!-- tabs:start -->

### **Python3**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,19 @@

<!-- 这里可写通用的实现逻辑 -->

**方法一:贪心 + 构造**

我们不妨假设当前需要构造的金额为 $s$,且我们已经构造出了 $[0,...,s-1]$ 内的所有金额。如果此时有一个新的硬币 $x$,我们把它加入到数组中,可以构造出 $[x, s+x-1]$ 内的所有金额。

接下来,分类讨论:

- 如果 $x \le s$,那么我们可以将上面两个区间合并,得到 $[0, s+x-1]$ 内的所有金额。
- 如果 $x \gt s$,那么我们就需要添加一个面值为 $s$ 的硬币,这样可以构造出 $[0, 2s-1]$ 内的所有金额。然后我们再考虑 $x$ 和 $s$ 的大小关系,继续分析。

因此,我们将数组 $coins$ 按照升序排序,然后从小到大遍历数组中的硬币。对于每个硬币 $x$,我们进行上述分类讨论,直到 $s > target$ 为止。

时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 是数组的长度。

<!-- tabs:start -->

### **Python3**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@ It can be shown that all integers from 1 to 20 are obtainable from the resulting

## Solutions

**Solution 1: Greedy + Construction**

Suppose the current amount we need to construct is $s$, and we have already constructed all amounts in $[0,...,s-1]$. If there is a new coin $x$, we add it to the array, which can construct all amounts in $[x, s+x-1]$.

Next, we discuss in two cases:

- If $x \le s$, then we can merge the two intervals above to get all amounts in $[0, s+x-1]$.
- If $x \gt s$, then we need to add a coin with a face value of $s$, so that we can construct all amounts in $[0, 2s-1]$. Then we consider the size relationship between $x$ and $s$ and continue to analyze.

Therefore, we sort the array $coins$ in ascending order, and then traverse the coins in the array from small to large. For each coin $x$, we discuss in the above two cases until $s > target$.

The time complexity is $O(n \times \log n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of the array.

<!-- tabs:start -->

### **Python3**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,27 +67,244 @@
<!-- 这里可写当前语言的特殊实现逻辑 -->

```python

mod = 10**9 + 7
mx = 10**5
fac = [1] * (mx + 1)
for i in range(2, mx + 1):
fac[i] = fac[i - 1] * i % mod


class Solution:
def numberOfSequence(self, n: int, sick: List[int]) -> int:
nums = [b - a - 1 for a, b in pairwise([-1] + sick + [n])]
ans = 1
s = sum(nums)
ans = fac[s]
for x in nums:
if x:
ans = ans * pow(fac[x], mod - 2, mod) % mod
for x in nums[1:-1]:
if x > 1:
ans = ans * pow(2, x - 1, mod) % mod
return ans
```

### **Java**

<!-- 这里可写当前语言的特殊实现逻辑 -->

```java

class Solution {
private static final int MOD = (int) (1e9 + 7);
private static final int MX = 100000;
private static final int[] FAC = new int[MX + 1];

static {
FAC[0] = 1;
for (int i = 1; i <= MX; i++) {
FAC[i] = (int) ((long) FAC[i - 1] * i % MOD);
}
}

public int numberOfSequence(int n, int[] sick) {
int m = sick.length;
int[] nums = new int[m + 1];
nums[0] = sick[0];
nums[m] = n - sick[m - 1] - 1;
for (int i = 1; i < m; i++) {
nums[i] = sick[i] - sick[i - 1] - 1;
}
int s = 0;
for (int x : nums) {
s += x;
}
int ans = FAC[s];
for (int x : nums) {
if (x > 0) {
ans = (int) ((long) ans * qpow(FAC[x], MOD - 2) % MOD);
}
}
for (int i = 1; i < nums.length - 1; ++i) {
if (nums[i] > 1) {
ans = (int) ((long) ans * qpow(2, nums[i] - 1) % MOD);
}
}
return ans;
}

private int qpow(long a, long n) {
long ans = 1;
for (; n > 0; n >>= 1) {
if ((n & 1) == 1) {
ans = ans * a % MOD;
}
a = a * a % MOD;
}
return (int) ans;
}
}
```

### **C++**

```cpp

const int MX = 1e5;
const int MOD = 1e9 + 7;
int fac[MX + 1];

auto init = [] {
fac[0] = 1;
for (int i = 1; i <= MX; ++i) {
fac[i] = 1LL * fac[i - 1] * i % MOD;
}
return 0;
}();

int qpow(long long a, long long n) {
long long ans = 1;
for (; n > 0; n >>= 1) {
if (n & 1) {
ans = (ans * a) % MOD;
}
a = (a * a) % MOD;
}
return ans;
}

class Solution {
public:
int numberOfSequence(int n, vector<int>& sick) {
int m = sick.size();
vector<int> nums(m + 1);

nums[0] = sick[0];
nums[m] = n - sick[m - 1] - 1;
for (int i = 1; i < m; i++) {
nums[i] = sick[i] - sick[i - 1] - 1;
}

int s = accumulate(nums.begin(), nums.end(), 0);
long long ans = fac[s];
for (int x : nums) {
if (x > 0) {
ans = ans * qpow(fac[x], MOD - 2) % MOD;
}
}
for (int i = 1; i < nums.size() - 1; ++i) {
if (nums[i] > 1) {
ans = ans * qpow(2, nums[i] - 1) % MOD;
}
}
return ans;
}
};
```

### **Go**

```go
const MX = 1e5
const MOD = 1e9 + 7

var fac [MX + 1]int

func init() {
fac[0] = 1
for i := 1; i <= MX; i++ {
fac[i] = fac[i-1] * i % MOD
}
}

func qpow(a, n int) int {
ans := 1
for n > 0 {
if n&1 == 1 {
ans = (ans * a) % MOD
}
a = (a * a) % MOD
n >>= 1
}
return ans
}

func numberOfSequence(n int, sick []int) int {
m := len(sick)
nums := make([]int, m+1)

nums[0] = sick[0]
nums[m] = n - sick[m-1] - 1
for i := 1; i < m; i++ {
nums[i] = sick[i] - sick[i-1] - 1
}

s := 0
for _, x := range nums {
s += x
}
ans := fac[s]
for _, x := range nums {
if x > 0 {
ans = ans * qpow(fac[x], MOD-2) % MOD
}
}
for i := 1; i < len(nums)-1; i++ {
if nums[i] > 1 {
ans = ans * qpow(2, nums[i]-1) % MOD
}
}
return ans
}
```

### **TypeScript**

```ts
const MX = 1e5;
const MOD: bigint = BigInt(1e9 + 7);
const fac: bigint[] = Array(MX + 1);

const init = (() => {
fac[0] = 1n;
for (let i = 1; i <= MX; ++i) {
fac[i] = (fac[i - 1] * BigInt(i)) % MOD;
}
return 0;
})();

function qpow(a: bigint, n: number): bigint {
let ans = 1n;
for (; n > 0; n >>= 1) {
if (n & 1) {
ans = (ans * a) % MOD;
}
a = (a * a) % MOD;
}
return ans;
}

function numberOfSequence(n: number, sick: number[]): number {
const m = sick.length;
const nums: number[] = Array(m + 1);
nums[0] = sick[0];
nums[m] = n - sick[m - 1] - 1;
for (let i = 1; i < m; i++) {
nums[i] = sick[i] - sick[i - 1] - 1;
}

const s = nums.reduce((acc, x) => acc + x, 0);
let ans = fac[s];
for (let x of nums) {
if (x > 0) {
ans = (ans * qpow(fac[x], Number(MOD) - 2)) % MOD;
}
}
for (let i = 1; i < nums.length - 1; ++i) {
if (nums[i] > 1) {
ans = (ans * qpow(2n, nums[i] - 1)) % MOD;
}
}
return Number(ans);
}
```

### **...**
Expand Down
Loading