From f171a81eecd61f6b6b84e450cbcd333c1d0c3400 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Wed, 19 Jul 2023 20:44:05 +0800 Subject: [PATCH] feat: add sql solution to lc problem: No.0918 No.0918.Maximum Sum Circular Subarray --- .../0874.Walking Robot Simulation/README.md | 6 +- .../README.md | 162 +++++++++++++++--- .../README_EN.md | 135 +++++++++++++-- 3 files changed, 258 insertions(+), 45 deletions(-) diff --git a/solution/0800-0899/0874.Walking Robot Simulation/README.md b/solution/0800-0899/0874.Walking Robot Simulation/README.md index 1c6e678b8c30e..7e4790b5b6c7e 100644 --- a/solution/0800-0899/0874.Walking Robot Simulation/README.md +++ b/solution/0800-0899/0874.Walking Robot Simulation/README.md @@ -88,15 +88,15 @@ 我们定义一个长度为 $5$ 的方向数组 $dirs=[0, 1, 0, -1, 0]$,数组中的相邻两个元素表示一个方向。即 $(dirs[0], dirs[1])$ 表示向北,而 $(dirs[1], dirs[2])$ 表示向东,以此类推。 -我们使用一个哈希表 $s$ 来存储所有障碍物的坐标,这样我们就可以在 $O(1)$ 的时间内判断下一步是否会遇到障碍物。 +我们使用一个哈希表 $s$ 来存储所有障碍物的坐标,这样可以在 $O(1)$ 的时间内判断下一步是否会遇到障碍物。 -我们使用两个变量 $x$ 和 $y$ 来表示机器人当前所在的坐标,初始时 $x = y = 0$。变量 $k$ 表示机器人当前的方向,答案变量 $ans$ 表示机器人距离原点的最大欧式距离的平方。 +另外,使用两个变量 $x$ 和 $y$ 来表示机器人当前所在的坐标,初始时 $x = y = 0$。变量 $k$ 表示机器人当前的方向,答案变量 $ans$ 表示机器人距离原点的最大欧式距离的平方。 接下来,我们遍历数组 $commands$ 中的每个元素 $c$: - 如果 $c = -2$,表示机器人向左转 $90$ 度,即 $k = (k + 3) \bmod 4$; - 如果 $c = -1$,表示机器人向右转 $90$ 度,即 $k = (k + 1) \bmod 4$; -- 否则,表示机器人向前移动 $c$ 个单位长度。我们将机器人当前的方向 $k$ 与方向数组 $dirs$ 结合,即可得到机器人在 $x$ 轴和 $y$ 轴上的增量。我们将 $c$ 个单位长度的增量分别累加到 $x$ 和 $y$ 上,并判断每次移动后的新坐标 $(x, y)$ 是否在障碍物的坐标中,如果不在,则更新答案 $ans$,否则停止模拟,进行下一条指令的模拟。 +- 否则,表示机器人向前移动 $c$ 个单位长度。我们将机器人当前的方向 $k$ 与方向数组 $dirs$ 结合,即可得到机器人在 $x$ 轴和 $y$ 轴上的增量。我们将 $c$ 个单位长度的增量分别累加到 $x$ 和 $y$ 上,并判断每次移动后的新坐标 $(nx, ny)$ 是否在障碍物的坐标中,如果不在,则更新答案 $ans$,否则停止模拟,进行下一条指令的模拟。 最后返回答案 $ans$ 即可。 diff --git a/solution/0900-0999/0918.Maximum Sum Circular Subarray/README.md b/solution/0900-0999/0918.Maximum Sum Circular Subarray/README.md index 7d5da3e8ce8fa..a92af6804291f 100644 --- a/solution/0900-0999/0918.Maximum Sum Circular Subarray/README.md +++ b/solution/0900-0999/0918.Maximum Sum Circular Subarray/README.md @@ -52,13 +52,32 @@ -环形子数组的最大和,可分为两种情况:无环最大和、有环最大和。求其较大值即可。 +**方法一:维护前缀最值** -无环最大和 s1 的求解可参考:[53. 最大子序和](/solution/0000-0099/0053.Maximum%20Subarray/README.md)。 +求环形子数组的最大和,可以分为两种情况: -对于有环最大和,我们可以转换为求最小子序和 s2,然后用 sum 减去最小子序和,得到有环的最大和。 +- 情况一:最大和的子数组不包含环形部分,即为普通的最大子数组和; +- 情况二:最大和的子数组包含环形部分,我们可以转换为:求数组总和减去最小子数组和。 -注意:若数组所有元素均不大于 0,直接返回无环最大和 s1 即可。 +因此,我们维护以下几个变量: + +- 前缀和最小值 $pmi$,初始值为 $0$; +- 前缀和最大值 $pmx$,初始值为 $-\infty$; +- 前缀和 $s$,初始值为 $0$; +- 最小子数组和 $smi$,初始值为 $\infty$; +- 答案 $ans$,初始值为 $-\infty$。 + +接下来,我们只需要遍历数组 $nums$,对于当前遍历到的元素 $x$,我们做以下更新操作: + +- 更新前缀和 $s = s + x$; +- 更新答案 $ans = \max(ans, s - pmi)$,即为情况一的答案(前缀和 $s$ 减去最小前缀和 $pmi$,可以得到最大子数组和); +- 更新 $smi = \min(smi, s - pmx)$,即为情况二的最小子数组和; +- 更新 $pmi = \min(pmi, s)$,即为最小前缀和; +- 更新 $pmx = \max(pmx, s)$,即为最大前缀和。 + +遍历结束,我们取 $ans$ 以及 $s - smi$ 的最大值作为答案返回即可。 + +时间复杂度 $O(n)$,其中 $n$ 为数组长度。空间复杂度 $O(1)$。 @@ -78,6 +97,20 @@ class Solution: return s1 if s1 <= 0 else max(s1, sum(nums) - s2) ``` +```python +class Solution: + def maxSubarraySumCircular(self, nums: List[int]) -> int: + pmi, pmx = 0, -inf + ans, s, smi = -inf, 0, inf + for x in nums: + s += x + ans = max(ans, s - pmi) + smi = min(smi, s - pmx) + pmi = min(pmi, s) + pmx = max(pmx, s) + return max(ans, s - smi) +``` + ### **Java** @@ -98,26 +131,21 @@ class Solution { } ``` -### **TypeScript** - -```ts -function maxSubarraySumCircular(nums: number[]): number { - let pre1 = nums[0], - pre2 = nums[0]; - let ans1 = nums[0], - ans2 = nums[0]; - let sum = nums[0]; - - for (let i = 1; i < nums.length; ++i) { - let cur = nums[i]; - sum += cur; - pre1 = Math.max(pre1 + cur, cur); - ans1 = Math.max(pre1, ans1); - - pre2 = Math.min(pre2 + cur, cur); - ans2 = Math.min(pre2, ans2); +```java +class Solution { + public int maxSubarraySumCircular(int[] nums) { + final int inf = 1 << 30; + int pmi = 0, pmx = -inf; + int ans = -inf, s = 0, smi = inf; + for (int x : nums) { + s += x; + ans = Math.max(ans, s - pmi); + smi = Math.min(smi, s - pmx); + pmi = Math.min(pmi, s); + pmx = Math.max(pmx, s); + } + return Math.max(ans, s - smi); } - return ans1 > 0 ? Math.max(ans1, sum - ans2) : ans1; } ``` @@ -140,6 +168,25 @@ public: }; ``` +```cpp +class Solution { +public: + int maxSubarraySumCircular(vector& nums) { + const int inf = 1 << 30; + int pmi = 0, pmx = -inf; + int ans = -inf, s = 0, smi = inf; + for (int x : nums) { + s += x; + ans = max(ans, s - pmi); + smi = min(smi, s - pmx); + pmi = min(pmi, s); + pmx = max(pmx, s); + } + return max(ans, s - smi); + } +}; +``` + ### **Go** ```go @@ -173,6 +220,75 @@ func min(a, b int) int { } ``` +```go +func maxSubarraySumCircular(nums []int) int { + const inf = 1 << 30 + pmi, pmx := 0, -inf + ans, s, smi := -inf, 0, inf + for _, x := range nums { + s += x + ans = max(ans, s-pmi) + smi = min(smi, s-pmx) + pmi = min(pmi, s) + pmx = max(pmx, s) + } + return max(ans, s-smi) +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` + +### **TypeScript** + +```ts +function maxSubarraySumCircular(nums: number[]): number { + let pre1 = nums[0], + pre2 = nums[0]; + let ans1 = nums[0], + ans2 = nums[0]; + let sum = nums[0]; + + for (let i = 1; i < nums.length; ++i) { + let cur = nums[i]; + sum += cur; + pre1 = Math.max(pre1 + cur, cur); + ans1 = Math.max(pre1, ans1); + + pre2 = Math.min(pre2 + cur, cur); + ans2 = Math.min(pre2, ans2); + } + return ans1 > 0 ? Math.max(ans1, sum - ans2) : ans1; +} +``` + +```ts +function maxSubarraySumCircular(nums: number[]): number { + const inf = 1 << 30; + let [pmi, pmx] = [0, -inf]; + let [ans, s, smi] = [-inf, 0, inf]; + for (const x of nums) { + s += x; + ans = Math.max(ans, s - pmi); + smi = Math.min(smi, s - pmx); + pmi = Math.min(pmi, s); + pmx = Math.max(pmx, s); + } + return Math.max(ans, s - smi); +} +``` + ### **...** ``` diff --git a/solution/0900-0999/0918.Maximum Sum Circular Subarray/README_EN.md b/solution/0900-0999/0918.Maximum Sum Circular Subarray/README_EN.md index dbd99e53db679..00e06b1cb7273 100644 --- a/solution/0900-0999/0918.Maximum Sum Circular Subarray/README_EN.md +++ b/solution/0900-0999/0918.Maximum Sum Circular Subarray/README_EN.md @@ -62,6 +62,20 @@ class Solution: return s1 if s1 <= 0 else max(s1, sum(nums) - s2) ``` +```python +class Solution: + def maxSubarraySumCircular(self, nums: List[int]) -> int: + pmi, pmx = 0, -inf + ans, s, smi = -inf, 0, inf + for x in nums: + s += x + ans = max(ans, s - pmi) + smi = min(smi, s - pmx) + pmi = min(pmi, s) + pmx = max(pmx, s) + return max(ans, s - smi) +``` + ### **Java** ```java @@ -80,26 +94,21 @@ class Solution { } ``` -### **TypeScript** - -```ts -function maxSubarraySumCircular(nums: number[]): number { - let pre1 = nums[0], - pre2 = nums[0]; - let ans1 = nums[0], - ans2 = nums[0]; - let sum = nums[0]; - - for (let i = 1; i < nums.length; ++i) { - let cur = nums[i]; - sum += cur; - pre1 = Math.max(pre1 + cur, cur); - ans1 = Math.max(pre1, ans1); - - pre2 = Math.min(pre2 + cur, cur); - ans2 = Math.min(pre2, ans2); +```java +class Solution { + public int maxSubarraySumCircular(int[] nums) { + final int inf = 1 << 30; + int pmi = 0, pmx = -inf; + int ans = -inf, s = 0, smi = inf; + for (int x : nums) { + s += x; + ans = Math.max(ans, s - pmi); + smi = Math.min(smi, s - pmx); + pmi = Math.min(pmi, s); + pmx = Math.max(pmx, s); + } + return Math.max(ans, s - smi); } - return ans1 > 0 ? Math.max(ans1, sum - ans2) : ans1; } ``` @@ -122,6 +131,25 @@ public: }; ``` +```cpp +class Solution { +public: + int maxSubarraySumCircular(vector& nums) { + const int inf = 1 << 30; + int pmi = 0, pmx = -inf; + int ans = -inf, s = 0, smi = inf; + for (int x : nums) { + s += x; + ans = max(ans, s - pmi); + smi = min(smi, s - pmx); + pmi = min(pmi, s); + pmx = max(pmx, s); + } + return max(ans, s - smi); + } +}; +``` + ### **Go** ```go @@ -155,6 +183,75 @@ func min(a, b int) int { } ``` +```go +func maxSubarraySumCircular(nums []int) int { + const inf = 1 << 30 + pmi, pmx := 0, -inf + ans, s, smi := -inf, 0, inf + for _, x := range nums { + s += x + ans = max(ans, s-pmi) + smi = min(smi, s-pmx) + pmi = min(pmi, s) + pmx = max(pmx, s) + } + return max(ans, s-smi) +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` + +### **TypeScript** + +```ts +function maxSubarraySumCircular(nums: number[]): number { + let pre1 = nums[0], + pre2 = nums[0]; + let ans1 = nums[0], + ans2 = nums[0]; + let sum = nums[0]; + + for (let i = 1; i < nums.length; ++i) { + let cur = nums[i]; + sum += cur; + pre1 = Math.max(pre1 + cur, cur); + ans1 = Math.max(pre1, ans1); + + pre2 = Math.min(pre2 + cur, cur); + ans2 = Math.min(pre2, ans2); + } + return ans1 > 0 ? Math.max(ans1, sum - ans2) : ans1; +} +``` + +```ts +function maxSubarraySumCircular(nums: number[]): number { + const inf = 1 << 30; + let [pmi, pmx] = [0, -inf]; + let [ans, s, smi] = [-inf, 0, inf]; + for (const x of nums) { + s += x; + ans = Math.max(ans, s - pmi); + smi = Math.min(smi, s - pmx); + pmi = Math.min(pmi, s); + pmx = Math.max(pmx, s); + } + return Math.max(ans, s - smi); +} +``` + ### **...** ```