Skip to content
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 @@ -50,48 +50,50 @@

### 方法一:枚举

枚举删除的位置 $i$,那么每一个位置 $i$ 的最长子数组长度为 $i$ 左边连续的 $1$ 的个数加上 $i$ 右边连续的 $1$ 的个数。
我们可以枚举每个删除的位置 $i$,然后计算左侧和右侧的连续 1 的个数,最后取最大值

因此,我们可以先遍历一遍数组,统计每个位置 $i$ 左边连续的 $1$ 的个数,记录在 `left` 数组;然后再从右向左遍历一遍数组,统计每个位置 $i$ 右边连续的 $1$ 的个数,记录在 `right` 数组,最后枚举删除的位置 $i$,求出最大值即可
具体地,我们使用两个长度为 $n+1$ 的数组 $left$ 和 $right$,其中 $left[i]$ 表示以 $nums[i-1]$ 结尾的连续 $1$ 的个数,而 $right[i]$ 表示以 $nums[i]$ 开头的连续 $1$ 的个数

时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 `nums` 的长度。
最终答案即为 $\max_{0 \leq i < n} \{left[i] + right[i+1]\}$。

时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $nums$ 的长度。

<!-- tabs:start -->

```python
class Solution:
def longestSubarray(self, nums: List[int]) -> int:
n = len(nums)
left = [0] * n
right = [0] * n
for i in range(1, n):
if nums[i - 1] == 1:
left = [0] * (n + 1)
right = [0] * (n + 1)
for i, x in enumerate(nums, 1):
if x:
left[i] = left[i - 1] + 1
for i in range(n - 2, -1, -1):
if nums[i + 1] == 1:
for i in range(n - 1, -1, -1):
if nums[i]:
right[i] = right[i + 1] + 1
return max(a + b for a, b in zip(left, right))
return max(left[i] + right[i + 1] for i in range(n))
```

```java
class Solution {
public int longestSubarray(int[] nums) {
int n = nums.length;
int[] left = new int[n];
int[] right = new int[n];
for (int i = 1; i < n; ++i) {
int[] left = new int[n + 1];
int[] right = new int[n + 1];
for (int i = 1; i <= n; ++i) {
if (nums[i - 1] == 1) {
left[i] = left[i - 1] + 1;
}
}
for (int i = n - 2; i >= 0; --i) {
if (nums[i + 1] == 1) {
for (int i = n - 1; i >= 0; --i) {
if (nums[i] == 1) {
right[i] = right[i + 1] + 1;
}
}
int ans = 0;
for (int i = 0; i < n; ++i) {
ans = Math.max(ans, left[i] + right[i]);
ans = Math.max(ans, left[i] + right[i + 1]);
}
return ans;
}
Expand All @@ -103,47 +105,158 @@ class Solution {
public:
int longestSubarray(vector<int>& nums) {
int n = nums.size();
vector<int> left(n);
vector<int> right(n);
for (int i = 1; i < n; ++i) {
if (nums[i - 1] == 1) {
vector<int> left(n + 1);
vector<int> right(n + 1);
for (int i = 1; i <= n; ++i) {
if (nums[i - 1]) {
left[i] = left[i - 1] + 1;
}
}
for (int i = n - 2; ~i; --i) {
if (nums[i + 1] == 1) {
for (int i = n - 1; ~i; --i) {
if (nums[i]) {
right[i] = right[i + 1] + 1;
}
}
int ans = 0;
for (int i = 0; i < n; ++i) {
ans = max(ans, left[i] + right[i]);
ans = max(ans, left[i] + right[i + 1]);
}
return ans;
}
};
```

```go
func longestSubarray(nums []int) int {
func longestSubarray(nums []int) (ans int) {
n := len(nums)
left := make([]int, n)
right := make([]int, n)
for i := 1; i < n; i++ {
left := make([]int, n+1)
right := make([]int, n+1)
for i := 1; i <= n; i++ {
if nums[i-1] == 1 {
left[i] = left[i-1] + 1
}
}
for i := n - 2; i >= 0; i-- {
if nums[i+1] == 1 {
for i := n - 1; i >= 0; i-- {
if nums[i] == 1 {
right[i] = right[i+1] + 1
}
}
ans := 0
for i := 0; i < n; i++ {
ans = max(ans, left[i]+right[i])
ans = max(ans, left[i]+right[i+1])
}
return
}
```

```ts
function longestSubarray(nums: number[]): number {
const n = nums.length;
const left: number[] = Array(n + 1).fill(0);
const right: number[] = Array(n + 1).fill(0);
for (let i = 1; i <= n; ++i) {
if (nums[i - 1]) {
left[i] = left[i - 1] + 1;
}
}
for (let i = n - 1; ~i; --i) {
if (nums[i]) {
right[i] = right[i + 1] + 1;
}
}
let ans = 0;
for (let i = 0; i < n; ++i) {
ans = Math.max(ans, left[i] + right[i + 1]);
}
return ans;
}
```

<!-- tabs:end -->

### 方法二:双指针

题目实际上是让我们找出一个最长的子数组,该子数组中最多只包含一个 $0$,删掉该子数组中的其中一个元素后,剩余的长度即为答案。

因此,我们可以用两个指针 $j$ 和 $i$ 分别指向子数组的左右边界,初始时 $j = 0$, $i = 0$。另外,我们用一个变量 $cnt$ 记录子数组中 $0$ 的个数。

接下来,我们移动右指针 $i$,如果 $nums[i] = 0$,则 $cnt$ 加 $1$。当 $cnt > 1$ 时,我们需要移动左指针 $j$,直到 $cnt \leq 1$。然后,我们更新答案,即 $ans = \max(ans, i - j)$。继续移动右指针 $i$,直到 $i$ 到达数组的末尾。

时间复杂度 $O(n)$,其中 $n$ 为数组 $nums$ 的长度。空间复杂度 $O(1)$。

<!-- tabs:start -->

```python
class Solution:
def longestSubarray(self, nums: List[int]) -> int:
ans = 0
cnt = j = 0
for i, x in enumerate(nums):
cnt += x ^ 1
while cnt > 1:
cnt -= nums[j] ^ 1
j += 1
ans = max(ans, i - j)
return ans
```

```java
class Solution {
public int longestSubarray(int[] nums) {
int ans = 0, n = nums.length;
for (int i = 0, j = 0, cnt = 0; i < n; ++i) {
cnt += nums[i] ^ 1;
while (cnt > 1) {
cnt -= nums[j++] ^ 1;
}
ans = Math.max(ans, i - j);
}
return ans;
}
}
```

```cpp
class Solution {
public:
int longestSubarray(vector<int>& nums) {
int ans = 0, n = nums.size();
for (int i = 0, j = 0, cnt = 0; i < n; ++i) {
cnt += nums[i] ^ 1;
while (cnt > 1) {
cnt -= nums[j++] ^ 1;
}
ans = max(ans, i - j);
}
return ans;
}
};
```

```go
func longestSubarray(nums []int) (ans int) {
cnt, j := 0, 0
for i, x := range nums {
cnt += x ^ 1
for ; cnt > 1; j++ {
cnt -= nums[j] ^ 1
}
ans = max(ans, i-j)
}
return ans
return
}
```

```ts
function longestSubarray(nums: number[]): number {
let [ans, cnt, j] = [0, 0, 0];
for (let i = 0; i < nums.length; ++i) {
cnt += nums[i] ^ 1;
while (cnt > 1) {
cnt -= nums[j++] ^ 1;
}
ans = Math.max(ans, i - j);
}
return ans;
}
```

Expand Down
Loading