你将会获得一系列视频片段,这些片段来自于一项持续时长为 T 秒的体育赛事。这些片段可能有所重叠,也可能长度不一。
视频片段 clips[i] 都用区间进行表示:开始于 clips[i][0] 并于 clips[i][1] 结束。我们甚至可以对这些片段自由地再剪辑,例如片段 [0, 7] 可以剪切成 [0, 1] + [1, 3] + [3, 7] 三部分。
我们需要将这些片段进行再剪辑,并将剪辑后的内容拼接成覆盖整个运动过程的片段([0, T])。返回所需片段的最小数目,如果无法完成该任务,则返回 -1
Input: clips = [[0,2],[4,6],[8,10],[1,9],[1,5],[5,9]], T = 10 Output: 3 Explanation: We take the clips [0,2], [8,10], [1,9]; a total of 3 clips. Then, we can reconstruct the sporting event as follows: We cut [1,9] into segments [1,2] + [2,8] + [8,9]. Now we have segments [0,2] + [2,8] + [8,10] which cover the sporting event [0, 10].
思路:
给了一堆区间,要求选取最少的区间,这些区间能覆盖[0, T]区间。要想最少区间,就要每个区间尽可能大,覆盖的范围广。
//直观想法,从起点0开始,获取到最长的片段终点,然后再用得到的额终点作为起点,在来获取新的片段终点,直到T为止
public int videoStitching(int[][] clips, int T) {
int res = 0;
int e = 0;
while (e < T) {
int tmp = e;
e = getLongest(e, clips);
if (tmp == e) return -1;
++res;
}
return res;
}
// 获取最长片段,输入起点,输出终点
private int getLongest(int s, int[][] clips) {
int max = 0;
for (int[] c : clips) {
if (c[0] <= s && c[1] >= s) max = Math.max(max, c[1]);
}
return max;
}
和jump game II类似
利用贪心算法,先对数组排序,先按开始数值从小到大排序,若两者相等,在按照结束节点排序。
用一个curend表示每一选中的最大片段范围的结束点数值,当遍历到clips[i][0]>curend,表示从i开始不能被之前的curend覆盖,所以需要选中一个新的区间,然后更新curend为最新得到的最大值。
public int videoStitching0(int[][] clips, int T) {
int len=clips.length;
Arrays.sort(clips, new Comparator() {
@Override
public int compare(int[] c1, int[] c2) {
if (c1[0] != c2[0]) {
return c1[0] - c2[0];
}
return c2[1] - c1[1];
}
});
if(clips[0][0]>0)return -1;
int res=0;
int curend=0;//代表被选中的范围的首尾
for(int i=0;i curend) {//有间隔,无法保证0--T被覆盖
return -1;
}
int tempend=curend;
while(i=T){
return res;
}
curend=tempend;
}
return -1;
}
不使用排序,更快一点,先用一个数组 end[T],下标代表的是其实节点,数组的数值代表以下标作为起始节点的片段的最大结束节点,然后再用循环来如何最少拼接。从0开始,开始为上个的结束的值+1,新的结束点为之前得到的end数组中的最大的结束的值
public int videoStitching2(int[][] clips, int T) {
int len=clips.length;
if(len==0)return -1;
int end[]=new int[T];
for(int t[]:clips){
if(t[0]>=T)continue;
end[t[0]]=Math.max(t[1],end[t[0]]);
}
int l=0,r=0,last=0,res=0;
while(true){
for(int i=l;i<=r;i++){
last=Math.max(last,end[i]);
}
if(last<=r)return -1;//相当于有断裂,clips[i][0]>curend
res++;
if(last>=T)return res;
l=r+1;
r=last;
}
}
动态规划,最慢
//动态规划
public int videoStitching3(int[][] clips, int T) {
int[][] dp= new int[T+1][T+1];
for(int i=0; i<=T; i++){
for(int j=0; j<=T; j++){
dp[i][j]=101;
}
}
for(int[] clip : clips){
int s=clip[0];
int r=clip[1];
for(int len=1; len<=T; len++){
for(int start=0; start<=T-len; start++){
int right= start+len;
if(s>right || r=right){dp[start][right]=1;}
else if(s<=start){dp[start][right]= Math.min(dp[start][right], dp[r][right]+1);}
else if( r>=right){dp[start][right]= Math.min(dp[start][right], dp[start][s]+1);}
else if(s>start && r