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<int[]>() {
            @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<len;){
            if(clips[i][0] > curend) {//有間隔,無法保證0--T被覆蓋
                return -1;
            }
            int tempend=curend;
            while(i<len&&clips[i][0]<=curend){//表示遍歷的第i個片段的起點在選取的end前面,所以要通過比較得出更大的end數值
                tempend=Math.max(tempend,clips[i][1]);
                i++;
            }
            res++;//最新的i位置的開始數值不在end前面,所以需要加1,需要在來一個區間
            if(tempend>=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<start){continue;}
                    if(s<=start && 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<right){dp[start][right]= Math.min(dp[start][right], dp[start][s]+1+dp[r][right]);}
                }
            }
        }
        return( dp[0][T]==101 ? -1 :dp[0][T]) ;

    }

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章