题目
给定0-1数组,找出连续1最长和次最长的2个子数组的起始位置和结束位置。
要求:
子数组长度大于等于1。
如果有多个子数组满足条件,按照数组下标由小到大只输出满足条件的前2个数组的起始位置和结束位置,
如果只有1个满足,输出1个子数组的起始位置和结束位置,
如果没有,输出-1 表示没找到。
例子:
输入:[0 1 1 1 0 0 0 1 1 1 0 1 1 0]
输出:1,3 7,9输入:[0 1 1 1 0 0 0 0 0 0 0 0 0 0]
输出:1,3输入:[0 0 0 0 0 0 0 0 0 0 0 0 0 0]
输出:-1
算法思路:
-
初始化变量
x1
、x2
、y1
和y2
为 -1。这些变量将存储最长和次长子数组的起始和结束位置。 -
遍历给定的二进制数组 (
arr
)。 -
在循环内部,检查当前元素是否为0或是否为数组的最后一个元素。如果是,说明当前的1的子数组结束了。
-
根据当前子数组的长度更新最长和次长子数组的位置。
-
维护子数组的起始和结束位置。
-
继续迭代。
-
在循环后,检查是否找到了有效的子数组(
x2
、y2
、x1
和y1
不等于 -1)。如果是真的,则打印最长和次长子数组的起始和结束位置。 -
如果没有找到有效的子数组,打印 -1。
算法实现
package algorithm;
public class TopicOne {
public static void main(String[] args) {
int arr[] = new int[]{0, 1 ,1 ,1 ,0 ,0 ,0 ,1, 1 ,1, 0, 1, 1 ,0};
int arr1[] =new int[]{0, 1, 1, 1 ,0, 0 ,0 ,0, 0, 0 ,0 ,0, 0, 0};
int arr2[] =new int[]{0 ,0 ,0 ,0, 0, 0, 0, 0, 0 ,0 ,0, 0 ,0 ,0};
System.out.println("*********测试1******");
getResult(arr);
System.out.println("*********测试2******");
getResult(arr1);
System.out.println("*********测试3******");
getResult(arr2);
}
public static void getResult(int[] arr){
int x1=-1;//次长左指针
int x2=-1;//最长左指针
int y1=-1;//次长右指针
int y2=-1;//最长右指针
int i=-1,j=-1;
for(int k=0;k<arr.length;k++){
/**
* 结尾1的判定
*起始如果是0 怎么处理
*
* 最长和次长
*/
if((k== arr.length-1||arr[k]==0)&&y2-x2<j-i){
x1=x2;
y1=y2;
y2=j;
x2=i;
} else if((k== arr.length-1||arr[k]==0)&&y1-x1<j-i){
y1=j;
x1=i;
}
if((k== arr.length-1||arr[k]==0)){
i=k+1;
}
j=k;
}
//x2代表最长的串 x2==-1说明最长都没有,就没有1 就返回-1
if(x2==-1){
System.out.println(-1);
//if走到一步说明x2!=-1 && y1==-1,那么就只有一个1的串
}else if(y1==-1){
System.out.println("x2="+x2+" y2="+y2);
//至少两个串
}else{
System.out.println("x2="+x2+" y2="+y2+"\n x1="+x1+",y1="+y1);
}
return;
}
}
-
该算法使用两对变量 (
x1
,y1
) 和 (x2
,y2
) 来追踪最长和次长的1的子数组的起始和结束位置。 -
循环遍历数组,每当遇到0或达到数组末尾时,检查并更新子数组的位置。
-
最后,算法打印最长和次长子数组的起始和结束位置,或者如果没有找到有效的子数组则打印 -1。
该算法的时间复杂度为 O(n),其中 n 是输入数组的长度,因为它只遍历一次数组。