diff --git a/solution/1300-1399/1351.Count Negative Numbers in a Sorted Matrix/README.md b/solution/1300-1399/1351.Count Negative Numbers in a Sorted Matrix/README.md index 345affd0c3d5a..e853505763d36 100644 --- a/solution/1300-1399/1351.Count Negative Numbers in a Sorted Matrix/README.md +++ b/solution/1300-1399/1351.Count Negative Numbers in a Sorted Matrix/README.md @@ -52,7 +52,7 @@ 遍历结束,返回答案。 -时间复杂度 $O(m + n)$。其中 $m$ 和 $n$ 分别为矩阵的行数和列数。 +时间复杂度 $O(m + n)$,其中 $m$ 和 $n$ 分别为矩阵的行数和列数。空间复杂度 $O(1)$。 **方法二:二分查找** @@ -60,7 +60,7 @@ 遍历结束,返回答案。 -时间复杂度 $O(m \times \log n)$。其中 $m$ 和 $n$ 分别为矩阵的行数和列数。 +时间复杂度 $O(m \times \log n)$,其中 $m$ 和 $n$ 分别为矩阵的行数和列数。空间复杂度 $O(1)$。 diff --git a/solution/1300-1399/1351.Count Negative Numbers in a Sorted Matrix/README_EN.md b/solution/1300-1399/1351.Count Negative Numbers in a Sorted Matrix/README_EN.md index d9c30dd08b1b2..6f09fff42c088 100644 --- a/solution/1300-1399/1351.Count Negative Numbers in a Sorted Matrix/README_EN.md +++ b/solution/1300-1399/1351.Count Negative Numbers in a Sorted Matrix/README_EN.md @@ -37,6 +37,24 @@ ## Solutions +**Solution 1: Start Traversing from the Bottom Left or Top Right** + +According to the characteristic that **both rows and columns are arranged in non-increasing order**, we can start traversing from the **bottom left corner** towards the **top right direction**. + +When encountering a negative number, it indicates that all elements to the right of the current position in this row are negative. We add the number of remaining elements in this row to the answer, that is, $n - j$, and move up a row, that is, $i \leftarrow i - 1$. Otherwise, move to the right column, that is, $j \leftarrow j + 1$. + +After the traversal is over, return the answer. + +The time complexity is $O(m + n)$, where $m$ and $n$ are the number of rows and columns of the matrix, respectively. The space complexity is $O(1)$. + +**Solution 2: Binary Search** + +Traverse each row, use binary search to find the first position less than $0$ in each row. All elements to the right of this position are negative, and add the number of negative numbers to the answer. + +After the traversal is over, return the answer. + +The time complexity is $O(m \times \log n)$, where $m$ and $n$ are the number of rows and columns of the matrix, respectively. The space complexity is $O(1)$. + ### **Python3** diff --git a/solution/1300-1399/1352.Product of the Last K Numbers/README_EN.md b/solution/1300-1399/1352.Product of the Last K Numbers/README_EN.md index 0b179aaccaa07..4b965fd8a45df 100644 --- a/solution/1300-1399/1352.Product of the Last K Numbers/README_EN.md +++ b/solution/1300-1399/1352.Product of the Last K Numbers/README_EN.md @@ -53,6 +53,16 @@ productOfNumbers.getProduct(2); // return 32. The product of the last 2 numbers ## Solutions +**Solution 1: Prefix Product** + +We initialize an array $s$, where $s[i]$ represents the product of the first $i$ numbers. + +When calling `add(num)`, we judge whether `num` is $0$. If it is, we set $s$ to `[1]`. Otherwise, we multiply the last element of $s$ by `num` and add the result to the end of $s$. + +When calling `getProduct(k)`, we now judge whether the length of $s$ is less than or equal to $k$. If it is, we return $0$. Otherwise, we return the last element of $s$ divided by the $k + 1$th element from the end of $s$. That is, $s[-1] / s[-k - 1]$. + +The time complexity is $O(1)$, and the space complexity is $O(n)$. Where $n$ is the number of times `add` is called. + ### **Python3** diff --git a/solution/1300-1399/1353.Maximum Number of Events That Can Be Attended/README.md b/solution/1300-1399/1353.Maximum Number of Events That Can Be Attended/README.md index 8f0ca39d985d8..ccccf888e54ec 100644 --- a/solution/1300-1399/1353.Maximum Number of Events That Can Be Attended/README.md +++ b/solution/1300-1399/1353.Maximum Number of Events That Can Be Attended/README.md @@ -57,7 +57,7 @@ 然后从优先队列中取出结束时间最小的会议,即为当前时间可以参加的会议,累加答案数。如果优先队列为空,则说明当前时间没有可以参加的会议。 -时间复杂度 $O(m\log n)$。其中 $m$, $n$ 分别表示会议的最大结束时间,以及会议的数量。 +时间复杂度 $O(m \times \log n)$,空间复杂度 $O(n)$。其中 $m$, $n$ 分别表示会议的最大结束时间,以及会议的数量。 diff --git a/solution/1300-1399/1353.Maximum Number of Events That Can Be Attended/README_EN.md b/solution/1300-1399/1353.Maximum Number of Events That Can Be Attended/README_EN.md index e215357542f7d..8ba50592951c2 100644 --- a/solution/1300-1399/1353.Maximum Number of Events That Can Be Attended/README_EN.md +++ b/solution/1300-1399/1353.Maximum Number of Events That Can Be Attended/README_EN.md @@ -41,6 +41,16 @@ Attend the third event on day 3. ## Solutions +**Solution 1: Hash Table + Greedy + Priority Queue** + +Define a hash table to record the start and end times of each meeting, where the key is the start time of the meeting, and the value is a list of end times. + +Enumerate the current time $s$, find all meetings that start at the current time, and add their end times to the priority queue (min heap). At the same time, the priority queue needs to remove all meetings that end before the current time. + +Then, take out the meeting with the smallest end time from the priority queue, which is the meeting that can be attended at the current time, and accumulate the answer count. If the priority queue is empty, it means that there are no meetings that can be attended at the current time. + +The time complexity is $O(m \times \log n)$, and the space complexity is $O(n)$. Where $m$ and $n$ represent the maximum end time of the meetings and the number of meetings, respectively. + ### **Python3** diff --git a/solution/1300-1399/1354.Construct Target Array With Multiple Sums/README.md b/solution/1300-1399/1354.Construct Target Array With Multiple Sums/README.md index 2f70357cedf60..b1b38f2374ae7 100644 --- a/solution/1300-1399/1354.Construct Target Array With Multiple Sums/README.md +++ b/solution/1300-1399/1354.Construct Target Array With Multiple Sums/README.md @@ -56,6 +56,14 @@ +**方法一:逆向构造 + 优先队列(大根堆)** + +我们发现,如果从数组 $arr$ 开始正向构造目标数组 $target$,每次都不好确定选择哪个下标 $i$,问题比较复杂。而如果我们从数组 $target$ 开始逆向构造,每次构造都一定是选择当前数组中最大的元素,这样就可以保证每次构造都是唯一的,问题比较简单。 + +因此,我们可以使用优先队列(大根堆)来存储数组 $target$ 中的元素,用一个变量 $s$ 记录数组 $target$ 中所有元素的和。每次从优先队列中取出最大的元素 $mx$,计算当前数组中除 $mx$ 以外的所有元素之和 $t$,如果 $t \lt 1$ 或者 $mx - t \lt 1$,则说明无法构造目标数组 $target$,返回 `false`。否则,我们计算 $mx \bmod t$,如果 $mx \bmod t = 0$,则令 $x = t$,否则令 $x = mx \bmod t$,将 $x$ 加入优先队列中,并更新 $s$ 的值,重复上述操作,直到优先队列中的所有元素都变为 $1$,此时返回 `true`。 + +时间复杂度 $O(n \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $target$ 的长度。 + ### **Python3** @@ -65,28 +73,18 @@ ```python class Solution: def isPossible(self, target: List[int]) -> bool: - if len(target) == 1: - return target[0] == 1 - - summ = sum(target) - maxHeap = [-num for num in target] - heapq.heapify(maxHeap) - - while -maxHeap[0] > 1: - maxi = -heapq.heappop(maxHeap) - restSum = summ - maxi - # Only occurs if n == 2. - if restSum == 1: - return True - updated = maxi % restSum - # Updated == 0 (invalid) or didn't change. - if updated == 0 or updated == maxi: + s = sum(target) + pq = [-x for x in target] + heapify(pq) + while -pq[0] > 1: + mx = -heappop(pq) + t = s - mx + if t == 0 or mx - t < 1: return False - heapq.heappush(maxHeap, -updated) - summ = summ - maxi + updated - + x = (mx % t) or t + heappush(pq, -x) + s = s - mx + x return True - ``` ### **Java** @@ -94,7 +92,119 @@ class Solution: ```java +class Solution { + public boolean isPossible(int[] target) { + PriorityQueue pq = new PriorityQueue<>(Collections.reverseOrder()); + long s = 0; + for (int x : target) { + s += x; + pq.offer((long) x); + } + while (pq.peek() > 1) { + long mx = pq.poll(); + long t = s - mx; + if (t == 0 || mx - t < 1) { + return false; + } + long x = mx % t; + if (x == 0) { + x = t; + } + pq.offer(x); + s = s - mx + x; + } + return true; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + bool isPossible(vector& target) { + priority_queue pq; + long long s = 0; + for (int i = 0; i < target.size(); i++) { + s += target[i]; + pq.push(target[i]); + } + while (pq.top() != 1) { + int mx = pq.top(); + pq.pop(); + long long t = s - mx; + if (t < 1 || mx - t < 1) { + return false; + } + int x = mx % t; + if (x == 0) { + x = t; + } + pq.push(x); + s = s - mx + x; + } + return true; + } +}; +``` + +### **Go** + +```go +func isPossible(target []int) bool { + pq := &hp{target} + s := 0 + for _, x := range target { + s += x + } + heap.Init(pq) + for target[0] > 1 { + mx := target[0] + t := s - mx + if t < 1 || mx-t < 1 { + return false + } + x := mx % t + if x == 0 { + x = t + } + target[0] = x + heap.Fix(pq, 0) + s = s - mx + x + } + return true +} + +type hp struct{ sort.IntSlice } + +func (h hp) Less(i, j int) bool { return h.IntSlice[i] > h.IntSlice[j] } +func (hp) Pop() (_ any) { return } +func (hp) Push(any) {} +``` +### **TypeScript** + +```ts +function isPossible(target: number[]): boolean { + const pq = new MaxPriorityQueue(); + let s = 0; + for (const x of target) { + s += x; + pq.enqueue(x); + } + while (pq.front().element > 1) { + const mx = pq.dequeue().element; + const t = s - mx; + if (t < 1 || mx - t < 1) { + return false; + } + const x = mx % t || t; + pq.enqueue(x); + s = s - mx + x; + } + return true; +} ``` ### **...** diff --git a/solution/1300-1399/1354.Construct Target Array With Multiple Sums/README_EN.md b/solution/1300-1399/1354.Construct Target Array With Multiple Sums/README_EN.md index 7839c8a3ff817..bc21eff07856a 100644 --- a/solution/1300-1399/1354.Construct Target Array With Multiple Sums/README_EN.md +++ b/solution/1300-1399/1354.Construct Target Array With Multiple Sums/README_EN.md @@ -53,6 +53,14 @@ ## Solutions +**Solution 1: Reverse Construction + Priority Queue (Max Heap)** + +We find that if we start from the array $arr$ and construct the target array $target$ forward, it is not easy to determine which index $i$ to choose each time, and the problem is relatively complex. However, if we start from the array $target$ and construct it in reverse, each construction must choose the largest element in the current array, which can ensure that each construction is unique, and the problem is relatively simple. + +Therefore, we can use a priority queue (max heap) to store the elements in the array $target$, and use a variable $s$ to record the sum of all elements in the array $target$. Each time we take out the largest element $mx$ from the priority queue, calculate the sum $t$ of all elements in the current array except $mx$. If $t < 1$ or $mx - t < 1$, it means that the target array $target$ cannot be constructed, and we return `false`. Otherwise, we calculate $mx \bmod t$. If $mx \bmod t = 0$, let $x = t$, otherwise let $x = mx \bmod t$, add $x$ to the priority queue, and update the value of $s$, repeat the above operations until all elements in the priority queue become $1$, then return `true`. + +The time complexity is $O(n \log n)$, and the space complexity is $O(n)$. Where $n$ is the length of the array $target$. + ### **Python3** @@ -60,34 +68,136 @@ ```python class Solution: def isPossible(self, target: List[int]) -> bool: - if len(target) == 1: - return target[0] == 1 - - summ = sum(target) - maxHeap = [-num for num in target] - heapq.heapify(maxHeap) - - while -maxHeap[0] > 1: - maxi = -heapq.heappop(maxHeap) - restSum = summ - maxi - # Only occurs if n == 2. - if restSum == 1: - return True - updated = maxi % restSum - # Updated == 0 (invalid) or didn't change. - if updated == 0 or updated == maxi: + s = sum(target) + pq = [-x for x in target] + heapify(pq) + while -pq[0] > 1: + mx = -heappop(pq) + t = s - mx + if t == 0 or mx - t < 1: return False - heapq.heappush(maxHeap, -updated) - summ = summ - maxi + updated - + x = (mx % t) or t + heappush(pq, -x) + s = s - mx + x return True - ``` ### **Java** ```java +class Solution { + public boolean isPossible(int[] target) { + PriorityQueue pq = new PriorityQueue<>(Collections.reverseOrder()); + long s = 0; + for (int x : target) { + s += x; + pq.offer((long) x); + } + while (pq.peek() > 1) { + long mx = pq.poll(); + long t = s - mx; + if (t == 0 || mx - t < 1) { + return false; + } + long x = mx % t; + if (x == 0) { + x = t; + } + pq.offer(x); + s = s - mx + x; + } + return true; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + bool isPossible(vector& target) { + priority_queue pq; + long long s = 0; + for (int i = 0; i < target.size(); i++) { + s += target[i]; + pq.push(target[i]); + } + while (pq.top() != 1) { + int mx = pq.top(); + pq.pop(); + long long t = s - mx; + if (t < 1 || mx - t < 1) { + return false; + } + int x = mx % t; + if (x == 0) { + x = t; + } + pq.push(x); + s = s - mx + x; + } + return true; + } +}; +``` + +### **Go** + +```go +func isPossible(target []int) bool { + pq := &hp{target} + s := 0 + for _, x := range target { + s += x + } + heap.Init(pq) + for target[0] > 1 { + mx := target[0] + t := s - mx + if t < 1 || mx-t < 1 { + return false + } + x := mx % t + if x == 0 { + x = t + } + target[0] = x + heap.Fix(pq, 0) + s = s - mx + x + } + return true +} + +type hp struct{ sort.IntSlice } + +func (h hp) Less(i, j int) bool { return h.IntSlice[i] > h.IntSlice[j] } +func (hp) Pop() (_ any) { return } +func (hp) Push(any) {} +``` +### **TypeScript** + +```ts +function isPossible(target: number[]): boolean { + const pq = new MaxPriorityQueue(); + let s = 0; + for (const x of target) { + s += x; + pq.enqueue(x); + } + while (pq.front().element > 1) { + const mx = pq.dequeue().element; + const t = s - mx; + if (t < 1 || mx - t < 1) { + return false; + } + const x = mx % t || t; + pq.enqueue(x); + s = s - mx + x; + } + return true; +} ``` ### **...** diff --git a/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.cpp b/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.cpp new file mode 100644 index 0000000000000..a86a02d47b8c3 --- /dev/null +++ b/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.cpp @@ -0,0 +1,26 @@ +class Solution { +public: + bool isPossible(vector& target) { + priority_queue pq; + long long s = 0; + for (int i = 0; i < target.size(); i++) { + s += target[i]; + pq.push(target[i]); + } + while (pq.top() != 1) { + int mx = pq.top(); + pq.pop(); + long long t = s - mx; + if (t < 1 || mx - t < 1) { + return false; + } + int x = mx % t; + if (x == 0) { + x = t; + } + pq.push(x); + s = s - mx + x; + } + return true; + } +}; \ No newline at end of file diff --git a/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.go b/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.go new file mode 100644 index 0000000000000..79fc1872a5c86 --- /dev/null +++ b/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.go @@ -0,0 +1,29 @@ +func isPossible(target []int) bool { + pq := &hp{target} + s := 0 + for _, x := range target { + s += x + } + heap.Init(pq) + for target[0] > 1 { + mx := target[0] + t := s - mx + if t < 1 || mx-t < 1 { + return false + } + x := mx % t + if x == 0 { + x = t + } + target[0] = x + heap.Fix(pq, 0) + s = s - mx + x + } + return true +} + +type hp struct{ sort.IntSlice } + +func (h hp) Less(i, j int) bool { return h.IntSlice[i] > h.IntSlice[j] } +func (hp) Pop() (_ any) { return } +func (hp) Push(any) {} \ No newline at end of file diff --git a/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.java b/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.java new file mode 100644 index 0000000000000..7ffe7d5f2a5d3 --- /dev/null +++ b/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.java @@ -0,0 +1,24 @@ +class Solution { + public boolean isPossible(int[] target) { + PriorityQueue pq = new PriorityQueue<>(Collections.reverseOrder()); + long s = 0; + for (int x : target) { + s += x; + pq.offer((long) x); + } + while (pq.peek() > 1) { + long mx = pq.poll(); + long t = s - mx; + if (t == 0 || mx - t < 1) { + return false; + } + long x = mx % t; + if (x == 0) { + x = t; + } + pq.offer(x); + s = s - mx + x; + } + return true; + } +} \ No newline at end of file diff --git a/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.py b/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.py index ec3ecc99ba728..b3af9c387bad1 100644 --- a/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.py +++ b/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.py @@ -1,23 +1,14 @@ class Solution: def isPossible(self, target: List[int]) -> bool: - if len(target) == 1: - return target[0] == 1 - - summ = sum(target) - maxHeap = [-num for num in target] - heapq.heapify(maxHeap) - - while -maxHeap[0] > 1: - maxi = -heapq.heappop(maxHeap) - restSum = summ - maxi - # Only occurs if n == 2. - if restSum == 1: - return True - updated = maxi % restSum - # Updated == 0 (invalid) or didn't change. - if updated == 0 or updated == maxi: + s = sum(target) + pq = [-x for x in target] + heapify(pq) + while -pq[0] > 1: + mx = -heappop(pq) + t = s - mx + if t == 0 or mx - t < 1: return False - heapq.heappush(maxHeap, -updated) - summ = summ - maxi + updated - + x = (mx % t) or t + heappush(pq, -x) + s = s - mx + x return True diff --git a/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.ts b/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.ts new file mode 100644 index 0000000000000..144be716e511b --- /dev/null +++ b/solution/1300-1399/1354.Construct Target Array With Multiple Sums/Solution.ts @@ -0,0 +1,19 @@ +function isPossible(target: number[]): boolean { + const pq = new MaxPriorityQueue(); + let s = 0; + for (const x of target) { + s += x; + pq.enqueue(x); + } + while (pq.front().element > 1) { + const mx = pq.dequeue().element; + const t = s - mx; + if (t < 1 || mx - t < 1) { + return false; + } + const x = mx % t || t; + pq.enqueue(x); + s = s - mx + x; + } + return true; +} diff --git a/solution/1300-1399/1356.Sort Integers by The Number of 1 Bits/README.md b/solution/1300-1399/1356.Sort Integers by The Number of 1 Bits/README.md index c6b709db77375..9c20ab32ecbaf 100644 --- a/solution/1300-1399/1356.Sort Integers by The Number of 1 Bits/README.md +++ b/solution/1300-1399/1356.Sort Integers by The Number of 1 Bits/README.md @@ -65,9 +65,9 @@ **方法一:自定义排序** -将数组 `arr` 按照题目要求排序,即按照二进制表示中数字 $1$ 的数目升序排序,如果存在多个数字二进制中 $1$ 的数目相同,则必须将它们按照数值大小升序排列。 +我们将数组 $arr$ 按照题目要求排序,即按照二进制表示中数字 $1$ 的数目升序排序,如果存在多个数字二进制中 $1$ 的数目相同,则必须将它们按照数值大小升序排列。 -时间复杂度 $O(n \times \log n)$,其中 $n$ 是数组 `arr` 的长度。 +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $arr$ 的长度。 diff --git a/solution/1300-1399/1356.Sort Integers by The Number of 1 Bits/README_EN.md b/solution/1300-1399/1356.Sort Integers by The Number of 1 Bits/README_EN.md index 2da22e3b00e41..4cd32e5727fdd 100644 --- a/solution/1300-1399/1356.Sort Integers by The Number of 1 Bits/README_EN.md +++ b/solution/1300-1399/1356.Sort Integers by The Number of 1 Bits/README_EN.md @@ -39,6 +39,12 @@ The sorted array by bits is [0,1,2,4,8,3,5,6,7] ## Solutions +**Solution 1: Custom Sorting** + +We sort the array $arr$ according to the requirements of the problem, that is, sort in ascending order according to the number of $1$s in the binary representation. If there are multiple numbers with the same number of $1$s in the binary representation, they must be sorted in ascending order by numerical value. + +The time complexity is $O(n \log n)$, and the space complexity is $O(n)$. Where $n$ is the length of the array $arr$. + ### **Python3** diff --git a/solution/1300-1399/1357.Apply Discount Every n Orders/README_EN.md b/solution/1300-1399/1357.Apply Discount Every n Orders/README_EN.md index 7fb2e4669088f..30bab34f95f77 100644 --- a/solution/1300-1399/1357.Apply Discount Every n Orders/README_EN.md +++ b/solution/1300-1399/1357.Apply Discount Every n Orders/README_EN.md @@ -65,6 +65,12 @@ cashier.getBill([2,3,5],[5,3,2]); // return 2500.0. 7th ## Solutions +**Solution 1: Hash Table + Simulation** + +Use a hash table $d$ to store the product ID and price, then traverse the product ID and quantity, calculate the total price, and then calculate the price after discount based on the discount. + +The time complexity of initialization is $O(n)$, where $n$ is the number of products. The time complexity of the `getBill` function is $O(m)$, where $m$ is the number of products purchased. The space complexity is $O(n)$. + ### **Python3** diff --git a/solution/1300-1399/1358.Number of Substrings Containing All Three Characters/README.md b/solution/1300-1399/1358.Number of Substrings Containing All Three Characters/README.md index 90a0216e68f84..07b935ab1026b 100644 --- a/solution/1300-1399/1358.Number of Substrings Containing All Three Characters/README.md +++ b/solution/1300-1399/1358.Number of Substrings Containing All Three Characters/README.md @@ -49,9 +49,9 @@ 我们用一个长度为 $3$ 的数组 $d$ 记录三种字符最近一次出现的位置,初始时均为 $-1$。 -遍历字符串 $s$,对于当前位置 $i$,我们先更新 $d[s[i]=i$,然后合法的字符串个数为 $min(d[0], d[1], d[2]) + 1$,累加到答案中。 +遍历字符串 $s$,对于当前位置 $i$,我们先更新 $d[s[i]]=i$,然后合法的字符串个数为 $\min(d[0], d[1], d[2]) + 1$,累加到答案中。 -时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为字符串 $s$ 的长度。 +时间复杂度 $O(n)$,其中 $n$ 为字符串 $s$ 的长度。空间复杂度 $O(1)$。 diff --git a/solution/1300-1399/1358.Number of Substrings Containing All Three Characters/README_EN.md b/solution/1300-1399/1358.Number of Substrings Containing All Three Characters/README_EN.md index b88d4038f9e5e..9eba5ba0f7eb6 100644 --- a/solution/1300-1399/1358.Number of Substrings Containing All Three Characters/README_EN.md +++ b/solution/1300-1399/1358.Number of Substrings Containing All Three Characters/README_EN.md @@ -42,6 +42,14 @@ ## Solutions +**Solution 1: Single Pass** + +We use an array $d$ of length $3$ to record the most recent occurrence of the three characters, initially all set to $-1$. + +We traverse the string $s$. For the current position $i$, we first update $d[s[i]]=i$, then the number of valid strings is $\min(d[0], d[1], d[2]) + 1$, which is accumulated to the answer. + +The time complexity is $O(n)$, where $n$ is the length of the string $s$. The space complexity is $O(1)$. + ### **Python3** diff --git a/solution/1300-1399/1359.Count All Valid Pickup and Delivery Options/README.md b/solution/1300-1399/1359.Count All Valid Pickup and Delivery Options/README.md index 55c04046af45f..3451c80ee0614 100644 --- a/solution/1300-1399/1359.Count All Valid Pickup and Delivery Options/README.md +++ b/solution/1300-1399/1359.Count All Valid Pickup and Delivery Options/README.md @@ -65,7 +65,7 @@ $$ 我们注意到 $f[i]$ 的值只与 $f[i - 1]$ 有关,所以可以用一个变量代替数组,降低空间复杂度。 -时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为订单数目。 +时间复杂度 $O(n)$,其中 $n$ 为订单数目。空间复杂度 $O(1)$。 diff --git a/solution/1300-1399/1359.Count All Valid Pickup and Delivery Options/README_EN.md b/solution/1300-1399/1359.Count All Valid Pickup and Delivery Options/README_EN.md index a8db24dfdbd58..01e430aacf5d4 100644 --- a/solution/1300-1399/1359.Count All Valid Pickup and Delivery Options/README_EN.md +++ b/solution/1300-1399/1359.Count All Valid Pickup and Delivery Options/README_EN.md @@ -45,6 +45,22 @@ This is an invalid order (P1,D2,P2,D1) because Pickup 2 is after of Delivery 2. ## Solutions +**Solution 1: Dynamic Programming** + +We define $f[i]$ as the number of all valid pickup/delivery sequences for $i$ orders. Initially, $f[1] = 1$. + +We can choose any of these $i$ orders as the last delivery order $D_i$, then its pickup order $P_i$ can be at any position in the previous $2 \times i - 1$, and the number of pickup/delivery sequences for the remaining $i - 1$ orders is $f[i - 1]$, so $f[i]$ can be expressed as: + +$$ +f[i] = i \times (2 \times i - 1) \times f[i - 1] +$$ + +The final answer is $f[n]$. + +We notice that the value of $f[i]$ is only related to $f[i - 1]$, so we can use a variable instead of an array to reduce the space complexity. + +The time complexity is $O(n)$, where $n$ is the number of orders. The space complexity is $O(1)$. + ### **Python3** diff --git a/solution/1300-1399/1360.Number of Days Between Two Dates/README_EN.md b/solution/1300-1399/1360.Number of Days Between Two Dates/README_EN.md index a3395a31c084d..51bba1442f0d5 100644 --- a/solution/1300-1399/1360.Number of Days Between Two Dates/README_EN.md +++ b/solution/1300-1399/1360.Number of Days Between Two Dates/README_EN.md @@ -25,6 +25,18 @@ ## Solutions +**Solution 1: Mathematics** + +First, we define a function `isLeapYear(year)` to determine whether the given year `year` is a leap year. If it is a leap year, return `true`, otherwise return `false`. + +Next, we define another function `daysInMonth(year, month)` to calculate the total number of days in the given year `year` and month `month`. We can use an array `days` to store the number of days in each month, where `days[1]` represents the number of days in February. If it is a leap year, it is $29$ days, otherwise it is $28$ days. + +Then, we define another function `calcDays(date)` to calculate the number of days from the given date `date` to `1971-01-01`. We can use `date.split("-")` to split the date `date` into year `year`, month `month`, and day `day` by `-`. Then we can use a loop to calculate the total number of days from `1971` to `year`, then calculate the total number of days from January to `month`, and finally add `day` days. + +Finally, we only need to return the absolute value of `calcDays(date1) - calcDays(date2)`. + +The time complexity is $O(y + m)$, where $y$ represents the number of years from the given date to `1971-01-01`, and $m$ represents the number of months of the given date. The space complexity is $O(1)$. + ### **Python3** diff --git a/solution/1300-1399/1361.Validate Binary Tree Nodes/README_EN.md b/solution/1300-1399/1361.Validate Binary Tree Nodes/README_EN.md index 5185b65e03129..cda45e908652b 100644 --- a/solution/1300-1399/1361.Validate Binary Tree Nodes/README_EN.md +++ b/solution/1300-1399/1361.Validate Binary Tree Nodes/README_EN.md @@ -43,7 +43,17 @@ ## Solutions -Union find. +**Solution 1: Union-Find** + +We can traverse each node $i$ and its corresponding left and right children $l$, $r$, using an array $vis$ to record whether the node has a parent: + +- If the child node already has a parent, it means there are multiple fathers, which does not meet the condition, so we return `false` directly. +- If the child node and the parent node are already in the same connected component, it means a cycle will be formed, which does not meet the condition, so we return `false` directly. +- Otherwise, we perform a union operation, set the corresponding position of the $vis$ array to `true`, and decrease the number of connected components by $1$. + +After the traversal, we check whether the number of connected components in the union-find set is $1$. If it is, we return `true`, otherwise, we return `false`. + +The time complexity is $O(n \times \alpha(n))$, and the space complexity is $O(n)$. Where $n$ is the number of nodes, and $\alpha(n)$ is the inverse Ackermann function, which is less than $5$. diff --git a/solution/1300-1399/1362.Closest Divisors/README_EN.md b/solution/1300-1399/1362.Closest Divisors/README_EN.md index ece1b81e5d40d..88e79279c91a5 100644 --- a/solution/1300-1399/1362.Closest Divisors/README_EN.md +++ b/solution/1300-1399/1362.Closest Divisors/README_EN.md @@ -40,6 +40,14 @@ ## Solutions +**Solution 1: Enumeration** + +We design a function $f(x)$ that returns two numbers whose product equals $x$ and the absolute difference between these two numbers is the smallest. We can start enumerating $i$ from $\sqrt{x}$. If $x$ can be divided by $i$, then $\frac{x}{i}$ is another factor. At this point, we have found two factors whose product equals $x$. We can return them directly. Otherwise, we decrease the value of $i$ and continue to enumerate. + +Next, we only need to calculate $f(num + 1)$ and $f(num + 2)$ respectively, and then compare the return values of the two functions. We return the one with the smaller absolute difference. + +The time complexity is $O(\sqrt{num})$, and the space complexity is $O(1)$. Where $num$ is the given integer. + ### **Python3** diff --git a/solution/1300-1399/1363.Largest Multiple of Three/README_EN.md b/solution/1300-1399/1363.Largest Multiple of Three/README_EN.md index 291b3d518911d..3a1c79b49e10b 100644 --- a/solution/1300-1399/1363.Largest Multiple of Three/README_EN.md +++ b/solution/1300-1399/1363.Largest Multiple of Three/README_EN.md @@ -40,6 +40,22 @@ ## Solutions +**Solution 1: Greedy + Dynamic Programming + Backtracking** + +We define $f[i][j]$ as the maximum length of selecting several numbers from the first $i$ numbers, so that the sum of the selected numbers modulo $3$ equals $j$. To make the selected numbers as large as possible, we need to select as many numbers as possible, so we need to make $f[i][j]$ as large as possible. We initialize $f[0][0] = 0$, and the rest of $f[0][j] = -\infty$. + +Consider how $f[i][j]$ transitions. We can choose not to select the $i$-th number, in which case $f[i][j] = f[i - 1][j]$; we can also choose to select the $i$-th number, in which case $f[i][j] = f[i - 1][(j - x_i \bmod 3 + 3) \bmod 3] + 1$, where $x_i$ represents the value of the $i$-th number. Therefore, we have the following state transition equation: + +$$ +f[i][j] = \max \{ f[i - 1][j], f[i - 1][(j - x_i \bmod 3 + 3) \bmod 3] + 1 \} +$$ + +If $f[n][0] \le 0$, then we cannot select any number, so the answer string is empty. Otherwise, we can backtrack through the $f$ array to find out the selected numbers. + +Define $i = n$, $j = 0$, start backtracking from $f[i][j]$, let $k = (j - x_i \bmod 3 + 3) \bmod 3$, if $f[i - 1][k] + 1 = f[i][j]$, then we have selected the $i$-th number, otherwise we have not selected the $i$-th number. If we have selected the $i$-th number, then we update $j$ to $k$, otherwise we keep $j$ unchanged. To make the number of the same length as large as possible, we should prefer to select larger numbers, so we should sort the array first. + +The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Where $n$ is the length of the array. + ### **Python3** diff --git a/solution/1300-1399/1365.How Many Numbers Are Smaller Than the Current Number/README_EN.md b/solution/1300-1399/1365.How Many Numbers Are Smaller Than the Current Number/README_EN.md index ac46b59c0fb17..3a2f8b52a1aac 100644 --- a/solution/1300-1399/1365.How Many Numbers Are Smaller Than the Current Number/README_EN.md +++ b/solution/1300-1399/1365.How Many Numbers Are Smaller Than the Current Number/README_EN.md @@ -46,6 +46,20 @@ For nums[4]=3 there exist three smaller numbers than it (1, 2 and 2). ## Solutions +**Solution 1: Sorting + Binary Search** + +We can make a copy of the array $nums$, denoted as $arr$, and then sort $arr$ in ascending order. + +Next, for each element $x$ in $nums$, we can use binary search to find the index $j$ of the first element that is greater than or equal to $x$. Then $j$ is the number of elements that are smaller than $x$. We can store $j$ in the answer array. + +The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Where $n$ is the length of the array $nums$. + +**Solution 2: Counting Sort + Prefix Sum** + +We notice that the range of elements in the array $nums$ is $[0, 100]$. Therefore, we can use the counting sort method to first count the number of each element in the array $nums$. Then we calculate the prefix sum of the counting array. Finally, we traverse the array $nums$. For each element $x$, we directly add the value of the element at index $x$ in the counting array to the answer array. + +The time complexity is $O(n + M)$, and the space complexity is $O(M)$. Where $n$ and $M$ are the length and the maximum value of the array $nums$, respectively. + ### **Python3** diff --git a/solution/1300-1399/1366.Rank Teams by Votes/README_EN.md b/solution/1300-1399/1366.Rank Teams by Votes/README_EN.md index 8f463f039b3c0..e0f8a4abb9006 100644 --- a/solution/1300-1399/1366.Rank Teams by Votes/README_EN.md +++ b/solution/1300-1399/1366.Rank Teams by Votes/README_EN.md @@ -56,6 +56,12 @@ X is the winner due to the tie-breaking rule. X has the same votes as W for the ## Solutions +**Solution 1: Counting + Custom Sorting** + +For each candidate, we can count the number of votes they receive in each ranking, and then compare the number of votes according to different rankings. If the number of votes is the same, we compare the letters. + +The time complexity is $O(n^2 \times \log n)$, and the space complexity is $O(n^2)$. Where $n$ is the number of candidates. + ### **Python3** diff --git a/solution/1300-1399/1367.Linked List in Binary Tree/README_EN.md b/solution/1300-1399/1367.Linked List in Binary Tree/README_EN.md index c49e98e6cdb31..47fe4a050730d 100644 --- a/solution/1300-1399/1367.Linked List in Binary Tree/README_EN.md +++ b/solution/1300-1399/1367.Linked List in Binary Tree/README_EN.md @@ -49,6 +49,19 @@ ## Solutions +**Solution 1: Recursion** + +We design a recursive function $dfs(head, root)$, which indicates whether the linked list $head$ corresponds to a subpath on the path starting with $root$ in the binary tree. The logic of the function $dfs(head, root)$ is as follows: + +- If the linked list $head$ is empty, it means that the linked list has been traversed, return `true`; +- If the binary tree $root$ is empty, it means that the binary tree has been traversed, but the linked list has not been traversed yet, return `false`; +- If the value of the binary tree $root$ is not equal to the value of the linked list $head$, return `false`; +- Otherwise, return $dfs(head.next, root.left)$ or $dfs(head.next, root.right)$. + +In the main function, we call $dfs(head, root)$ for each node of the binary tree. As long as one returns `true`, it means that the linked list is a subpath of the binary tree, return `true`; if all nodes return `false`, it means that the linked list is not a subpath of the binary tree, return `false`. + +The time complexity is $O(n^2)$, and the space complexity is $O(n)$. Where $n$ is the number of nodes in the binary tree. + ### **Python3** diff --git a/solution/1300-1399/1368.Minimum Cost to Make at Least One Valid Path in a Grid/README_EN.md b/solution/1300-1399/1368.Minimum Cost to Make at Least One Valid Path in a Grid/README_EN.md index a1a770fb67387..7b24b0f70b7d7 100644 --- a/solution/1300-1399/1368.Minimum Cost to Make at Least One Valid Path in a Grid/README_EN.md +++ b/solution/1300-1399/1368.Minimum Cost to Make at Least One Valid Path in a Grid/README_EN.md @@ -59,7 +59,13 @@ The total cost = 3. ## Solutions -BFS using deque. +**Solution 1: Double-ended Queue BFS** + +This problem is essentially a shortest path model, but what we are looking for is the minimum number of direction changes. + +In an undirected graph where the edge weights are only 0 and 1, we can use a double-ended queue for BFS. The principle is that when the weight of the point that can be expanded currently is 0, it is added to the front of the queue; when the weight is 1, it is added to the end of the queue. + +> If the weight of an edge is 0, then the weight of the newly expanded node is the same as the weight of the current queue head node. Obviously, it can be used as the starting point for the next expansion.