1、题目描述
2、解题思路
2.1 数组已知
针对每一个 0 都计算出它左右两侧连续的数字 1 的个数,最后返回邻居 1 最多的那个,别忘了加一。
2.2 数组未知
使用动态规划的解法,动态规划往往抓着最后一个元素做文章,本题也是。
下列说的“已使用”和“未使用”指的是把 0 变为 1 的操作。
设 dp[i][0] 表示未使用的情况下,以 i 为结尾的最长的 1 的长度;
设 dp[i][1] 表示已使用的情况下,以 i 为结尾的最长的 1 的长度。
状态转移方程如下:
1、若 nums[i] == 1,则直接继承上一个位置的值,dp[i][0] = dp[i-1][0] + 1, dp[i][1] = dp[i-1][1] + 1;
2、若 nums[i] == 0,则 dp[i][0] = 0,即现在位置已经是 0 了,还不使用就长度变为 0;dp[i][1] = dp[i][0] + 1,即把当前位置的 0 变为 1。
3、解题代码
3.1 数组已知
class Solution {
public int findMaxConsecutiveOnes(int[] nums) {
int length = nums.length;
int pre = 0;
// key 为 0 的索引,value 为 0 左右两侧的连续数字 1 的个数
Map<Integer, Integer> map = new HashMap<>();
// 从左往右
for (int i = 0; i < length; i++) {
if (nums[i] == 0) {
map.put(i, pre);
pre = 0;
} else { // 1
pre++;
}
}
// 从右往左
pre = 0;
for (int i = length - 1; i >= 0; i--) {
if (nums[i] == 0) {
map.put(i, map.get(i) + pre);
pre = 0;
} else { // 1
pre++;
}
}
if (map.size() == 0) return length;
int max = 0;
for (Integer value : map.values()) {
max = Math.max(max, value);
}
return max + 1;
}
}
3.2 数组未知
class Solution {
public int findMaxConsecutiveOnes(int[] nums) {
int length = nums.length;
// dp[i][0] 表示以 nums[i] 结尾未使用操作下的最长 1 的长度
// dp[i][1] 表示以 nums[i] 结尾的已经使用操作的最长 1 的长度
int[][] dp = new int[length][2];
int max = 0;
for (int i = 0; i < length; i++) {
if (i == 0) {
if (nums[0] == 1) {
dp[0][0] = 1;
dp[0][1] = 1;
} else {
dp[0][1] = 1;
}
} else {
if (nums[i] == 0) {
dp[i][0] = 0; // 没有以 0 结尾的 1 序列
dp[i][1] = dp[i - 1][0] + 1; // 把当前位置的 0 变为 1
} else {
// 当前位置为 1,直接继承上一个位置的状态
dp[i][0] = dp[i - 1][0] + 1;
dp[i][1] = dp[i - 1][1] + 1;
}
}
max = Math.max(max, Math.max(dp[i][0], dp[i][1]));
}
return max;
}
}