一、题目内容
二、题目分析
虽然这道题目的标签是双指针解法,但是我拿到的第一想法是这样的:
先创造两个大大的boolean数组,如上图示例,第一个数组a的长度为数组最后一个数字加一,也就是26,;第二个数组长度为27。然后呢,将[0,2]、[5,10]之类的,只要在范围内的都赋值为true。然后就得到了两个赋值完毕的boolean数组,那么只要两个数组都为true,是不是就是重合的部分了?再然后把重合部分的两端加入list中,最后输出即可。
这种做法固然很容易理解,但是我试了一下,还是会超时。原因就在于start和end最高可取到十的九次方,这样做复杂度太高了。所以我们引进双指针算法。
首先大家看图:
我们定义两个指针分别指向A的和B,然后假如他们现在都指向第一个部分,那么在什么情况下,他们有交集?什么情况下没有?
首先我们令A的左端为a1,右端为a2;B的左端为b1,右端为b2.
则有:
当a1>b2时,说明A的最左端比B的最右端还要靠右,这时候是不是要让指向B的指针指向下一个了?
同理,当b1>a2时,说明B的最左端比A的最右端还要靠右, 这时候是要将指向A的指针指向下一个。
那么如果上述条件都不满足,说明当前的两个小块是有公共集的。公共集的左端是A、B左端中较大的那个,公共集的右端是A、B右端较小的那个(观察可得),我们分别将他们记为min和max,然后将min和max加入提前准备好的list即可。
接下来我们要将其中一个的指针指向下一个。当B的右端比A的右端靠右的时候,就将A的指针指向下一个,否则就将B的指针指向下一个,如此循环,直到两个指针有一个到达的临界点。
代码:
public int[][] intervalIntersection(int[][] firstList, int[][] secondList) {
if(firstList==null||secondList==null)
return firstList==null?firstList:secondList;
List<int[]>list=new ArrayList<>();
int p1=0,p2=0;
while(p1<firstList.length&&p2<secondList.length){
int a1=firstList[p1][0],a2=firstList[p1][1];
int b1=secondList[p2][0],b2=secondList[p2][1];
if(a1>b2){
p2++;
continue;
}
if(b1>a2){
p1++;
continue;
}
int min=Math.max(a1,b1);
int max=Math.min(a2,b2);
list.add(new int[]{min,max});
if(b2>a2){
p1++;
}
else{
p2++;
}
}
return list.toArray(new int[list.size()][]);
}
三、尾言
HURRY!TIME WON'T WAIT YOU!