题目
给定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 就返回-1if(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 是输入数组的长度,因为它只遍历一次数组。