Skip to content

Commit fc9a143

Browse files
authored
Merge branch 'doocs:main' into main
2 parents 3480784 + 94e5644 commit fc9a143

File tree

77 files changed

+32651
-28063
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+32651
-28063
lines changed

images/starcharts.svg

Lines changed: 28106 additions & 27994 deletions
Loading

solution/0200-0299/0277.Find the Celebrity/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ tags:
2222

2323
<p>现在你想要确认这个 “名人” 是谁,或者确定这里没有&nbsp;“名人”。而你唯一能做的就是问诸如 “A&nbsp;你好呀,请问你认不认识&nbsp;B呀?”&nbsp;的问题,以确定 A 是否认识 B。你需要在(渐近意义上)尽可能少的问题内来确定这位 “名人” 是谁(或者确定这里没有 “名人”)。</p>
2424

25-
<p>在本题中,你可以使用辅助函数&nbsp;<code>bool knows(a, b)</code>&nbsp;获取到 A&nbsp;是否认识 B。请你来实现一个函数&nbsp;<code>int findCelebrity(n)</code>。</p>
25+
<p>给定整数&nbsp;<code>n</code>&nbsp;和一个辅助函数&nbsp;<code>bool knows(a, b)</code>&nbsp;用来获取&nbsp;<code>a</code> 是否认识&nbsp;<code>b</code>。实现一个函数&nbsp;<code>int findCelebrity(n)</code>。派对最多只会有一个 “名人” 参加。</p>
2626

27-
<p>派对最多只会有一个 “名人” 参加。若&nbsp;“名人” 存在,请返回他/她的编号;若&nbsp;“名人”&nbsp;不存在,请返回&nbsp;<code>-1</code>。</p>
27+
<p>若&nbsp;“名人” 存在,请返回他/她的编号;若&nbsp;“名人”&nbsp;不存在,请返回&nbsp;<code>-1</code>。</p>
28+
29+
<p><strong>注意</strong>&nbsp;<code>n x n</code>&nbsp;的二维数组&nbsp;<code>graph</code>&nbsp;给定的输入并不是&nbsp;<strong>直接</strong>&nbsp;提供给你的,而是&nbsp;<strong>只能</strong>&nbsp;通过辅助函数 <code>knows</code>&nbsp;获取。<code>graph[i][j] == 1</code>&nbsp;表示&nbsp;<code>i</code> 认识 <code>j</code>,而&nbsp;<code>graph[i][j] == 0</code>&nbsp;表示&nbsp;<code>j</code>&nbsp;不认识&nbsp;<code>i</code>。</p>
2830

2931
<p>&nbsp;</p>
3032

solution/0800-0899/0805.Split Array With Same Average/README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ tags:
6262

6363
### 方法一:折半查找 + 二进制枚举
6464

65-
根据题目要求,要判断是否可以将数组 `nums` 划分为两个子数组 $A$ 和 $B$,使得两个子数组的平均值相等。
65+
根据题目要求,要判断是否可以将数组 $\textit{nums}$ 划分为两个子数组 $A$ 和 $B$,使得两个子数组的平均值相等。
6666

67-
我们记数组 `nums` 的和为 $s$,元素个数为 $n$。子数组 $A$ 的和以及个数分别为 $s_1$ 和 $k$,那么子数组 $B$ 的和为 $s_2 = s - s_1$,个数为 $n - k$,即:
67+
我们记数组 $\textit{nums}$ 的和为 $s$,元素个数为 $n$。子数组 $A$ 的和以及个数分别为 $s_1$ 和 $k$,那么子数组 $B$ 的和为 $s_2 = s - s_1$,个数为 $n - k$,即:
6868

6969
$$
7070
\frac{s_1}{k} = \frac{s_2}{n - k} = \frac{s-s_1}{n-k}
@@ -82,25 +82,25 @@ $$
8282
\frac{s_1}{k} = \frac{s}{n}
8383
$$
8484

85-
也就是说,要我们找出一个子数组 $A$,使得其平均值等于数组 `nums` 的平均值。我们考虑将数组 `nums` 每个元素都减去数组 `nums` 的平均值,这样问题就转化为了在数组 `nums` 中找出一个子数组,使得其和为 $0$。
85+
也就是说,要我们找出一个子数组 $A$,使得其平均值等于数组 $\textit{nums}$ 的平均值。我们考虑将数组 $\textit{nums}$ 每个元素都减去数组 $\textit{nums}$ 的平均值,这样问题就转化为了在数组 $\textit{nums}$ 中找出一个子数组,使得其和为 $0$。
8686

87-
但是,数组 `nums` 的平均值可能不是整数,浮点数计算可能存在精度问题,我们不妨将数组 `nums` 中的每个元素都乘以 $n$,即 $nums[i] \leftarrow nums[i] \times n$,上述式子就变成:
87+
但是,数组 $\textit{nums}$ 的平均值可能不是整数,浮点数计算可能存在精度问题,我们不妨将数组 $\textit{nums}$ 中的每个元素都乘以 $n$,即 $nums[i] \leftarrow nums[i] \times n$,上述式子就变成:
8888

8989
$$
9090
\frac{s_1\times n}{k} = s
9191
$$
9292

93-
此时我们将数组 `nums` 中每个元素都减去整数 $s$,题目就转化为:在数组 $nums$ 中找出一个子数组 $A$,使得其和为 $0$。
93+
此时我们将数组 $\textit{nums}$ 中每个元素都减去整数 $s$,题目就转化为:在数组 $nums$ 中找出一个子数组 $A$,使得其和为 $0$。
9494

95-
数组 `nums` 的长度范围为 $[1, 30]$,如果我们使用暴力枚举子数组的方法,时间复杂度为 $O(2^n)$,会超时。我们可以使用折半查找的方法,将时间复杂度降低到 $O(2^{n/2})$。
95+
数组 $\textit{nums}$ 的长度范围为 $[1, 30]$,如果我们使用暴力枚举子数组的方法,时间复杂度为 $O(2^n)$,会超时。我们可以使用折半查找的方法,将时间复杂度降低到 $O(2^{n/2})$。
9696

97-
我们将数组 `nums` 分成左右两部分,那么子数组 $A$ 可能存在三种情况:
97+
我们将数组 $\textit{nums}$ 分成左右两部分,那么子数组 $A$ 可能存在三种情况:
9898

99-
1. 子数组 $A$ 完全在数组 `nums` 的左半部分;
100-
2. 子数组 $A$ 完全在数组 `nums` 的右半部分;
101-
3. 子数组 $A$ 一部分在数组 `nums` 的左半部分,一部分在数组 `nums` 的右半部分。
99+
1. 子数组 $A$ 完全在数组 $\textit{nums}$ 的左半部分;
100+
2. 子数组 $A$ 完全在数组 $\textit{nums}$ 的右半部分;
101+
3. 子数组 $A$ 一部分在数组 $\textit{nums}$ 的左半部分,一部分在数组 $\textit{nums}$ 的右半部分。
102102

103-
我们可以使用二进制枚举的方法,先枚举左半部分所有子数组的和,如果存在一个子数组和为 $0$,直接返回 `true`,否则我们将其存入哈希表 `vis` 中;然后枚举右半部分所有子数组的和,如果存在一个子数组和为 $0$,直接返回 `true`,否则我们判断此时哈希表 `vis` 中是否存在该和的相反数,如果存在,直接返回 `true`
103+
我们可以使用二进制枚举的方法,先枚举左半部分所有子数组的和,如果存在一个子数组和为 $0$,直接返回 `true`,否则我们将其存入哈希表 $\textit{vis}$ 中;然后枚举右半部分所有子数组的和,如果存在一个子数组和为 $0$,直接返回 `true`,否则我们判断此时哈希表 $\textit{vis}$ 中是否存在该和的相反数,如果存在,直接返回 `true`
104104

105105
需要注意的是,我们不能同时全选左半部分和右半部分,因为这样会导致子数组 $B$ 为空,这是不符合题意的。在实现上,我们只需要考虑数组的 $n-1$ 个数。
106106

solution/0800-0899/0805.Split Array With Same Average/README_EN.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,51 @@ tags:
5858

5959
<!-- solution:start -->
6060

61-
### Solution 1
61+
### Solution 1: Binary Search + Binary Enumeration
62+
63+
According to the problem requirements, we need to determine if the array $\textit{nums}$ can be divided into two subarrays $A$ and $B$ such that the average values of the two subarrays are equal.
64+
65+
Let the sum of the array $\textit{nums}$ be $s$, and the number of elements be $n$. The sum and number of elements of subarray $A$ are $s_1$ and $k$, respectively. Then the sum of subarray $B$ is $s_2 = s - s_1$, and the number of elements is $n - k$. Thus:
66+
67+
$$
68+
\frac{s_1}{k} = \frac{s_2}{n - k} = \frac{s-s_1}{n-k}
69+
$$
70+
71+
Rearranging, we get:
72+
73+
$$
74+
s_1 \times (n-k) = (s-s_1) \times k
75+
$$
76+
77+
Simplifying, we get:
78+
79+
$$
80+
\frac{s_1}{k} = \frac{s}{n}
81+
$$
82+
83+
This means we need to find a subarray $A$ such that its average value equals the average value of the array $\textit{nums}$. We consider subtracting the average value of the array $\textit{nums}$ from each element of the array $\textit{nums}$, transforming the problem into finding a subarray in the array $\textit{nums}$ whose sum is $0$.
84+
85+
However, the average value of the array $\textit{nums}$ may not be an integer, and floating-point calculations may have precision issues. We can multiply each element of the array $\textit{nums}$ by $n$, i.e., $nums[i] \leftarrow nums[i] \times n$. The above equation becomes:
86+
87+
$$
88+
\frac{s_1\times n}{k} = s
89+
$$
90+
91+
Now, we subtract the integer $s$ from each element of the array $\textit{nums}$, transforming the problem into finding a subarray $A$ in the array $nums$ whose sum is $0$.
92+
93+
The length of the array $\textit{nums}$ ranges from $[1, 30]$. If we use brute force to enumerate subarrays, the time complexity is $O(2^n)$, which will time out. We can use binary search to reduce the time complexity to $O(2^{n/2})$.
94+
95+
We divide the array $\textit{nums}$ into left and right parts. The subarray $A$ can exist in three cases:
96+
97+
1. Subarray $A$ is entirely in the left part of the array $\textit{nums}$;
98+
2. Subarray $A$ is entirely in the right part of the array $\textit{nums}$;
99+
3. Subarray $A$ is partially in the left part and partially in the right part of the array $\textit{nums}$.
100+
101+
We can use binary enumeration to first enumerate the sums of all subarrays in the left part. If there is a subarray with a sum of $0$, we return `true` immediately. Otherwise, we store the sums in a hash table $\textit{vis}$. Then we enumerate the sums of all subarrays in the right part. If there is a subarray with a sum of $0$, we return `true` immediately. Otherwise, we check if the hash table $\textit{vis}$ contains the opposite of the current sum. If it does, we return `true`.
102+
103+
Note that we cannot select all elements from both the left and right parts simultaneously, as this would leave subarray $B$ empty, which does not meet the problem requirements. In implementation, we only need to consider $n-1$ elements of the array.
104+
105+
The time complexity is $O(n \times 2^{\frac{n}{2}})$, and the space complexity is $O(2^{\frac{n}{2}})$.
62106

63107
<!-- tabs:start -->
64108

solution/0800-0899/0808.Soup Servings/README_EN.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,32 @@ So the total probability of A becoming empty first plus half the probability tha
6565

6666
<!-- solution:start -->
6767

68-
### Solution 1
68+
### Solution 1: Memoization Search
69+
70+
In this problem, since each operation is a multiple of $25$, we can consider every $25ml$ of soup as one unit. This reduces the data scale to $\left \lceil \frac{n}{25} \right \rceil$.
71+
72+
We design a function $dfs(i, j)$, which represents the probability result when there are $i$ units of soup $A$ and $j$ units of soup $B$ remaining.
73+
74+
When $i \leq 0$ and $j \leq 0$, it means both soups are finished, and we should return $0.5$. When $i \leq 0$, it means soup $A$ is finished first, and we should return $1$. When $j \leq 0$, it means soup $B$ is finished first, and we should return $0$.
75+
76+
Next, for each operation, we have four choices:
77+
78+
- Take $4$ units from soup $A$ and $0$ units from soup $B$;
79+
- Take $3$ units from soup $A$ and $1$ unit from soup $B$;
80+
- Take $2$ units from soup $A$ and $2$ units from soup $B$;
81+
- Take $1$ unit from soup $A$ and $3$ units from soup $B$.
82+
83+
Each choice has a probability of $0.25$, so we can derive:
84+
85+
$$
86+
dfs(i, j) = 0.25 \times (dfs(i - 4, j) + dfs(i - 3, j - 1) + dfs(i - 2, j - 2) + dfs(i - 1, j - 3))
87+
$$
88+
89+
We use memoization to store the results of the function.
90+
91+
Additionally, we find that when $n=4800$, the result is $0.999994994426$, and the required precision is $10^{-5}$. As $n$ increases, the result gets closer to $1$. Therefore, when $n \gt 4800$, we can directly return $1$.
92+
93+
The time complexity is $O(C^2)$, and the space complexity is $O(C^2)$. In this problem, $C=200$.
6994

7095
<!-- tabs:start -->
7196

solution/0800-0899/0809.Expressive Words/README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ tags:
3131
<p><strong>示例:</strong></p>
3232

3333
<pre>
34-
<strong>输入:</strong>
34+
<strong>输入:</strong>
3535
s = "heeellooo"
3636
words = ["hello", "hi", "helo"]
3737
<strong>输出:</strong>1
@@ -58,17 +58,17 @@ words = ["hello", "hi", "helo"]
5858

5959
### 方法一:遍历计数 + 双指针
6060

61-
我们可以遍历数组 `words`,对于数组中的每个单词 $t$,判断 $t$ 是否可以通过扩张得到 $s$,如果可以,那么答案加一。
61+
我们可以遍历数组 $\textit{words}$,对于数组中的每个单词 $t$,判断 $t$ 是否可以通过扩张得到 $s$,如果可以,那么答案加一。
6262

63-
因此,问题的关键在于判断单词 $t$ 是否可以通过扩张得到 $s$。这里我们通过一个 $check(s, t)$ 函数来判断。函数的具体实现逻辑如下:
63+
因此,问题的关键在于判断单词 $t$ 是否可以通过扩张得到 $s$。这里我们通过一个 $\textit{check}(s, t)$ 函数来判断。函数的具体实现逻辑如下:
6464

65-
首先判断 $s$ 和 $t$ 的长度关系,如果 $t$ 的长度大于 $s$,直接返回 `false`;否则,我们用双指针 $i$ 和 $j$ 分别指向 $s$ 和 $t$,初始时 $i$ 和 $j$ 的值均为 $0$。
65+
首先判断 $s$ 和 $t$ 的长度关系,如果 $t$ 的长度大于 $s$,直接返回 $\textit{false}$;否则,我们用双指针 $i$ 和 $j$ 分别指向 $s$ 和 $t$,初始时 $i$ 和 $j$ 的值均为 $0$。
6666

67-
如果 $i$ 和 $j$ 指向的字符不同,那么 $t$ 无法通过扩张得到 $s$,直接返回 `false`;否则,我们需要判断 $i$ 指向的字符的连续出现次数 $c_1$ 和 $j$ 指向的字符的连续出现次数 $c_2$ 的关系。如果 $c_1 \lt c_2$ 或者 $c_1 \lt 3$ 并且 $c_1 \neq c_2$,那么 $t$ 无法通过扩张得到 $s$,直接返回 `false`;否则,将 $i$ 和 $j$ 分别右移 $c_1$ 和 $c_2$ 次。继续判断。
67+
如果 $i$ 和 $j$ 指向的字符不同,那么 $t$ 无法通过扩张得到 $s$,直接返回 $\textit{false}$;否则,我们需要判断 $i$ 指向的字符的连续出现次数 $c_1$ 和 $j$ 指向的字符的连续出现次数 $c_2$ 的关系。如果 $c_1 \lt c_2$ 或者 $c_1 \lt 3$ 并且 $c_1 \neq c_2$,那么 $t$ 无法通过扩张得到 $s$,直接返回 $\textit{false}$;否则,将 $i$ 和 $j$ 分别右移 $c_1$ 和 $c_2$ 次。继续判断。
6868

69-
如果 $i$ 和 $j$ 都到达了字符串的末尾,那么 $t$ 可以通过扩张得到 $s$,返回 `true`,否则返回 `false`
69+
如果 $i$ 和 $j$ 都到达了字符串的末尾,那么 $t$ 可以通过扩张得到 $s$,返回 $\textit{true}$,否则返回 $\textit{false}$
7070

71-
时间复杂度 $O(n \times m + \sum_{i=0}^{m-1} w_i)$,其中 $n$ 和 $m$ 分别为字符串 $s$ 和数组 $words$ 的长度,而 $w_i$ 为数组 $words$ 中第 $i$ 个单词的长度。
71+
时间复杂度 $O(n \times m + \sum_{i=0}^{m-1} w_i)$,其中 $n$ 和 $m$ 分别为字符串 $s$ 和数组 $\textit{words}$ 的长度,而 $w_i$ 为数组 $\textit{words}$ 中第 $i$ 个单词的长度。
7272

7373
<!-- tabs:start -->
7474

solution/0800-0899/0809.Expressive Words/README_EN.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ tags:
4141
<pre>
4242
<strong>Input:</strong> s = &quot;heeellooo&quot;, words = [&quot;hello&quot;, &quot;hi&quot;, &quot;helo&quot;]
4343
<strong>Output:</strong> 1
44-
<strong>Explanation:</strong>
44+
<strong>Explanation:</strong>
4545
We can extend &quot;e&quot; and &quot;o&quot; in the word &quot;hello&quot; to get &quot;heeellooo&quot;.
4646
We can&#39;t extend &quot;helo&quot; to get &quot;heeellooo&quot; because the group &quot;ll&quot; is not size 3 or more.
4747
</pre>
@@ -68,7 +68,19 @@ We can&#39;t extend &quot;helo&quot; to get &quot;heeellooo&quot; because the gr
6868

6969
<!-- solution:start -->
7070

71-
### Solution 1
71+
### Solution 1: Traversal Counting + Two Pointers
72+
73+
We can traverse the array $\textit{words}$, and for each word $t$ in the array, check if $t$ can be expanded to obtain $s$. If it can, increment the answer by one.
74+
75+
Therefore, the key problem is to determine if the word $t$ can be expanded to obtain $s$. We use a function $\textit{check}(s, t)$ to determine this. The implementation logic of the function is as follows:
76+
77+
First, check the length relationship between $s$ and $t$. If the length of $t$ is greater than $s$, return $\textit{false}$ directly. Otherwise, use two pointers $i$ and $j$ to point to $s$ and $t$, respectively, both initially set to $0$.
78+
79+
If the characters pointed to by $i$ and $j$ are different, then $t$ cannot be expanded to obtain $s$, and we return $\textit{false}$. Otherwise, we need to check the relationship between the consecutive occurrence counts of the characters pointed to by $i$ and $j$, denoted as $c_1$ and $c_2$. If $c_1 \lt c_2$ or $c_1 \lt 3$ and $c_1 \neq c_2$, then $t$ cannot be expanded to obtain $s$, and we return $\textit{false}$. Otherwise, move $i$ and $j$ to the right by $c_1$ and $c_2$ times, respectively, and continue checking.
80+
81+
If both $i$ and $j$ reach the end of the strings, then $t$ can be expanded to obtain $s$, and we return $\textit{true}$. Otherwise, we return $\textit{false}$.
82+
83+
The time complexity is $O(n \times m + \sum_{i=0}^{m-1} w_i)$, where $n$ and $m$ are the lengths of the string $s$ and the array $\textit{words}$, respectively, and $w_i$ is the length of the $i$-th word in the array $\textit{words}$.
7284

7385
<!-- tabs:start -->
7486

0 commit comments

Comments
 (0)