Video Stitching1024 视频拼接

你将会获得一系列视频片段,这些片段来自于一项持续时长为 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

 

 

 

你可能感兴趣的:(java,算法)