题解 | # 乘积为正数的最长连续子数组#
乘积为正数的最长连续子数组
http://www.nowcoder.com/practice/0112b9b5a09048d89309f55ea666db91
思路:
-
如果负数的个数是偶数,那么就是数组的长度。
-
如果是奇数,那么就判断是从左往右 还是 从右往左长
例子: 1 1 1 -1 1 1 1 1
对于子数组1 1 1 1 -1 和子数组2 -1 1 1 1 1 找最长。不用管其它的负数,因为子数组1 中负数去掉 最右边 -1 那么肯定剩下的负数个数为偶数。
-
遇到0 重置,重新开始新一轮判断
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
for(int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
System.out.println(find(arr, n));
}
static int find(int[] arr, int n) {
//确定如果负数总数为奇数时
//最左一个奇数和最右一个奇数的下标
int right1 = n, left1 = -1;
for(int i = 0; i < n ;i ++) {
if(arr[i] < 0 ) {
right1 = i;
}
if(arr[n - 1 - i] < 0) {
left1 = n - 1 - i;
}
}
//按照0来分割子数组
//z是每个子数组的正数, f是负数
//从左到右遍历 和从右到左遍历 确定 负数总数为奇数时 res为多少
int z = 0, f = 0, res = 0;
int z1 = 0, f1 = 0;
for(int i = 0; i < n; i++) {
//一个实例 1 1 -1 1 -1 1
//i < right1 || f == 1 保证可以到最右别 -1 时 依旧可以res++。
//(f1 == 0 && n-1-i > left1) 保证 最后一个1 也可以 res++
if(i < right1 || f == 1 || (f1 == 0 && n-1-i > left1)) {
if(arr[i] > 0 ){
z++;//完全就是统计正数的个数
} else if(arr[i] < 0) {
f++;//统计负数的个数
if(f == 2) {//一旦有俩负数了,就可以当成正数
z += 2;
f -= 2;
}
} else {
//遇到0 则重置,重新再来
//相当于新开始一个子数组
z = 0;
f = 0;
}
}
res = Math.max(res, z);
//从右开始
if(n-1-i > left1 || f1 == 1 || (f1 == 0 && n-1-i > left1)) {
if(arr[n-1-i] > 0 ){
z1++;
} else if(arr[n-1-i] < 0) {
f1++;
if(f1 == 2) {
z1 += 2;
f1 -= 2;
}
} else {
z1 = 0;
f1 = 0;
}
}
res = Math.max(res, z1);
}
return res;
}
}