Skip to content

feat: add solutions to lc problem: No.0918 #1245

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 1 commit into from
Jul 19, 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
6 changes: 3 additions & 3 deletions solution/0800-0899/0874.Walking Robot Simulation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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$ 即可。

Expand Down
162 changes: 139 additions & 23 deletions solution/0900-0999/0918.Maximum Sum Circular Subarray/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)$。

<!-- tabs:start -->

Expand All @@ -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**

<!-- 这里可写当前语言的特殊实现逻辑 -->
Expand All @@ -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;
}
```

Expand All @@ -140,6 +168,25 @@ public:
};
```

```cpp
class Solution {
public:
int maxSubarraySumCircular(vector<int>& 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
Expand Down Expand Up @@ -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);
}
```

### **...**

```
Expand Down
135 changes: 116 additions & 19 deletions solution/0900-0999/0918.Maximum Sum Circular Subarray/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
}
```

Expand All @@ -122,6 +131,25 @@ public:
};
```

```cpp
class Solution {
public:
int maxSubarraySumCircular(vector<int>& 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
Expand Down Expand Up @@ -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);
}
```

### **...**

```
Expand Down