Skip to content

[pull] main from doocs:main #168

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

Merged
merged 4 commits into from
Aug 2, 2024
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 @@ -73,11 +73,11 @@ tags:

### 方法一:栈

我们观察题目中的操作,可以发现,每一次都会在字符串的任意位置插入字符串 `"abc"`,所以每次插入操作之后,字符串的长度都会增加 $3$。如果字符串 $s$ 有效,那么它的长度一定是 $3$ 的倍数。因此,我们先对字符串 $s$ 的长度进行判断,如果不是 $3$ 的倍数,那么 $s$ 一定无效,可以直接返回 `false`
我们观察题目中的操作,可以发现,每一次都会在字符串的任意位置插入字符串 $\textit{"abc"}$,所以每次插入操作之后,字符串的长度都会增加 $3$。如果字符串 $s$ 有效,那么它的长度一定是 $3$ 的倍数。因此,我们先对字符串 $s$ 的长度进行判断,如果不是 $3$ 的倍数,那么 $s$ 一定无效,可以直接返回 $\textit{false}$

接下来我们遍历字符串 $s$ 的每个字符 $c$,我们先将字符 $c$ 压入栈 $t$ 中。如果此时栈 $t$ 的长度大于等于 $3$,并且栈顶的三个元素组成了字符串 `"abc"`,那么我们就将栈顶的三个元素弹出。然后继续遍历字符串 $s$ 的下一个字符。
接下来我们遍历字符串 $s$ 的每个字符 $c$,我们先将字符 $c$ 压入栈 $t$ 中。如果此时栈 $t$ 的长度大于等于 $3$,并且栈顶的三个元素组成了字符串 $\textit{"abc"}$,那么我们就将栈顶的三个元素弹出。然后继续遍历字符串 $s$ 的下一个字符。

遍历结束之后,如果栈 $t$ 为空,那么说明字符串 $s$ 有效,返回 `true`,否则返回 `false`
遍历结束之后,如果栈 $t$ 为空,那么说明字符串 $s$ 有效,返回 $\textit{true}$;否则,返回 $\textit{false}$

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ Thus, "abcabcababcc" is valid.

### Solution 1: Stack

If the string is valid, it's length must be the multiple of $3$.
We observe the operations in the problem and find that each time a string $\textit{"abc"}$ is inserted at any position in the string. Therefore, after each insertion operation, the length of the string increases by $3$. If the string $s$ is valid, its length must be a multiple of $3$. Thus, we first check the length of the string $s$. If it is not a multiple of $3$, then $s$ must be invalid, and we can directly return $\textit{false}$.

We traverse the string and push every character into the stack $t$. If the size of stack $t$ is greater than or equal to $3$ and the top three elements of stack $t$ constitute the string `"abc"`, we pop the top three elements. Then we continue to traverse the next character of the string $s$.
Next, we traverse each character $c$ in the string $s$. We first push the character $c$ onto the stack $t$. If the length of the stack $t$ is greater than or equal to $3$, and the top three elements of the stack form the string $\textit{"abc"}$, then we pop the top three elements from the stack. We then continue to traverse the next character in the string $s$.

When the traversal is over, if the stack $t$ is empty, the string $s$ is valid, return `true`, otherwise return `false`.
After the traversal, if the stack $t$ is empty, it means the string $s$ is valid, and we return $\textit{true}$; otherwise, we return $\textit{false}$.

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

<!-- tabs:start -->

Expand Down
104 changes: 104 additions & 0 deletions solution/1300-1399/1395.Count Number of Teams/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -527,4 +527,108 @@ function numTeams(rating: number[]): number {

<!-- solution:end -->

<!-- solution:start -->

### 方法三:记忆化搜索

<!-- tabs:start -->

#### TypeScript

```ts
function numTeams(rating: number[]): number {
const n = rating.length;
const f: Record<Type, number[][]> = {
asc: Array.from({ length: n }, () => Array(3).fill(-1)),
desc: Array.from({ length: n }, () => Array(3).fill(-1)),
};

const fn = (i: number, available: number, type: Type) => {
if (!available) {
return 1;
}
if (f[type][i][available] !== -1) {
return f[type][i][available];
}

let ans = 0;
for (let j = i + 1; j < n; j++) {
if (rating[j] > rating[i]) {
if (type === 'asc') {
ans += fn(j, available - 1, 'asc');
}
} else {
if (type === 'desc') {
ans += fn(j, available - 1, 'desc');
}
}
}
f[type][i][available] = ans;

return ans;
};

let ans = 0;
for (let i = 0; i < n; i++) {
ans += fn(i, 2, 'asc') + fn(i, 2, 'desc');
}

return ans;
}

type Type = 'asc' | 'desc';
```

#### JavaScript

```js
/**
* @param {number[]} rating
* @return {number}
*/
var numTeams = function (rating) {
const n = rating.length;
const f = {
asc: Array.from({ length: n }, () => Array(3).fill(-1)),
desc: Array.from({ length: n }, () => Array(3).fill(-1)),
};

const fn = (i, available, type) => {
if (!available) {
return 1;
}
if (f[type][i][available] !== -1) {
return f[type][i][available];
}

let ans = 0;
for (let j = i + 1; j < n; j++) {
if (rating[j] > rating[i]) {
if (type === 'asc') {
ans += fn(j, available - 1, 'asc');
}
} else {
if (type === 'desc') {
ans += fn(j, available - 1, 'desc');
}
}
}
f[type][i][available] = ans;

return ans;
};

let ans = 0;
for (let i = 0; i < n; i++) {
ans += fn(i, 2, 'asc') + fn(i, 2, 'desc');
}

return ans;
};
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- problem:end -->
106 changes: 105 additions & 1 deletion solution/1300-1399/1395.Count Number of Teams/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ tags:
<pre>
<strong>Input:</strong> rating = [2,5,3,4,1]
<strong>Output:</strong> 3
<strong>Explanation:</strong> We can form three teams given the conditions. (2,3,4), (5,4,1), (5,3,1).
<strong>Explanation:</strong> We can form three teams given the conditions. (2,3,4), (5,4,1), (5,3,1).
</pre>

<p><strong class="example">Example 2:</strong></p>
Expand Down Expand Up @@ -525,4 +525,108 @@ function numTeams(rating: number[]): number {

<!-- solution:end -->

<!-- solution:start -->

### Solution 3: Recursion + Memoization

<!-- tabs:start -->

#### TypeScript

```ts
function numTeams(rating: number[]): number {
const n = rating.length;
const f: Record<Type, number[][]> = {
asc: Array.from({ length: n }, () => Array(3).fill(-1)),
desc: Array.from({ length: n }, () => Array(3).fill(-1)),
};

const fn = (i: number, available: number, type: Type) => {
if (!available) {
return 1;
}
if (f[type][i][available] !== -1) {
return f[type][i][available];
}

let ans = 0;
for (let j = i + 1; j < n; j++) {
if (rating[j] > rating[i]) {
if (type === 'asc') {
ans += fn(j, available - 1, 'asc');
}
} else {
if (type === 'desc') {
ans += fn(j, available - 1, 'desc');
}
}
}
f[type][i][available] = ans;

return ans;
};

let ans = 0;
for (let i = 0; i < n; i++) {
ans += fn(i, 2, 'asc') + fn(i, 2, 'desc');
}

return ans;
}

type Type = 'asc' | 'desc';
```

#### JavaScript

```js
/**
* @param {number[]} rating
* @return {number}
*/
var numTeams = function (rating) {
const n = rating.length;
const f = {
asc: Array.from({ length: n }, () => Array(3).fill(-1)),
desc: Array.from({ length: n }, () => Array(3).fill(-1)),
};

const fn = (i, available, type) => {
if (!available) {
return 1;
}
if (f[type][i][available] !== -1) {
return f[type][i][available];
}

let ans = 0;
for (let j = i + 1; j < n; j++) {
if (rating[j] > rating[i]) {
if (type === 'asc') {
ans += fn(j, available - 1, 'asc');
}
} else {
if (type === 'desc') {
ans += fn(j, available - 1, 'desc');
}
}
}
f[type][i][available] = ans;

return ans;
};

let ans = 0;
for (let i = 0; i < n; i++) {
ans += fn(i, 2, 'asc') + fn(i, 2, 'desc');
}

return ans;
};
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- problem:end -->
43 changes: 43 additions & 0 deletions solution/1300-1399/1395.Count Number of Teams/Solution3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* @param {number[]} rating
* @return {number}
*/
var numTeams = function (rating) {
const n = rating.length;
const f = {
asc: Array.from({ length: n }, () => Array(3).fill(-1)),
desc: Array.from({ length: n }, () => Array(3).fill(-1)),
};

const fn = (i, available, type) => {
if (!available) {
return 1;
}
if (f[type][i][available] !== -1) {
return f[type][i][available];
}

let ans = 0;
for (let j = i + 1; j < n; j++) {
if (rating[j] > rating[i]) {
if (type === 'asc') {
ans += fn(j, available - 1, 'asc');
}
} else {
if (type === 'desc') {
ans += fn(j, available - 1, 'desc');
}
}
}
f[type][i][available] = ans;

return ans;
};

let ans = 0;
for (let i = 0; i < n; i++) {
ans += fn(i, 2, 'asc') + fn(i, 2, 'desc');
}

return ans;
};
41 changes: 41 additions & 0 deletions solution/1300-1399/1395.Count Number of Teams/Solution3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
function numTeams(rating: number[]): number {
const n = rating.length;
const f: Record<Type, number[][]> = {
asc: Array.from({ length: n }, () => Array(3).fill(-1)),
desc: Array.from({ length: n }, () => Array(3).fill(-1)),
};

const fn = (i: number, available: number, type: Type) => {
if (!available) {
return 1;
}
if (f[type][i][available] !== -1) {
return f[type][i][available];
}

let ans = 0;
for (let j = i + 1; j < n; j++) {
if (rating[j] > rating[i]) {
if (type === 'asc') {
ans += fn(j, available - 1, 'asc');
}
} else {
if (type === 'desc') {
ans += fn(j, available - 1, 'desc');
}
}
}
f[type][i][available] = ans;

return ans;
};

let ans = 0;
for (let i = 0; i < n; i++) {
ans += fn(i, 2, 'asc') + fn(i, 2, 'desc');
}

return ans;
}

type Type = 'asc' | 'desc';
Loading