开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 10 天,点击查看活动详情
LeetCode1493:删掉一个元素以后全为 1 的最长子数组
给你一个二进制数组 nums ,你需要从中删掉一个元素。
请你在删掉元素的结果数组中,返回最长的且只包含 1 的非空子数组的长度。
如果不存在这样的子数组,请返回 0 。 提示 1:
输入: nums = [1,1,0,1]
输出: 3
解释: 删掉位置 2 的数后,[1,1,1] 包含 3 个 1 。
示例 2:
输入: nums = [0,1,1,1,0,1,1,0,1]
输出: 5
解释: 删掉位置 4 的数字后,[0,1,1,1,1,1,0,1] 的最长全 1 子数组为 [1,1,1,1,1] 。
示例 3:
输入: nums = [1,1,1]
输出: 2
解释: 你必须要删除一个元素。
提示:
nums[i]要么是0要么是1。
思路分析
先计算出0的个数,然后new一个二位数组arr arr[i][0]表示第i个零左边连1有多少个,arr[i][1]代表第i个零右边连续1有多少个; 然后再遍历这个数组,将其左右连续1相加,取最小即可
这里有个小技巧:在计算0的个数的时候0处的值为新数组arr第一个下标的负数
考虑最长子数组中包含一个值为0的元素,不能包含两个;可以以滑动窗口中值为0的个数作为判断条件控制窗口滑动
算法代码
public int longestSubarray(int[] nums) {
int zeroNum = 0;
int len = nums.length;
for (int i = 0; i < len; i++) {
if (nums[i] == 0) {
zeroNum++;
nums[i] = -zeroNum + 1;
}
}
if (zeroNum == 0) return len - 1;
int[][] arr = new int[zeroNum][2];
int left = 0, right = 0;
for (int j = 0; j < len; j++) {
int cur = nums[j];
if (cur <= 0) {
arr[-cur][0] = left;
left = 0;
}
if (cur == 1) left++;
}
for (int k = len - 1; k >= 0; k--) {
int cur = nums[k];
if (cur <= 0) {
arr[-cur][1] = right;
right = 0;
}
if (cur == 1) right++;
}
int ans = 0;
for (int m = 0; m < zeroNum; m++) {
ans = Math.max((arr[m][0] + arr[m][1]), ans);
}
return ans;
}
结果详情
算法复杂度
- 空间复杂度:
- 时间复杂度:
在掘金(JUEJIN)一起进步,一起成长!