leetcode 1024. 视频拼接
题意:
你将会获得一系列视频片段,这些片段来自于一项持续时长为 T 秒的体育赛事。这些片段可能有所重叠,也可能长度不一。
视频片段 clips[i] 都用区间进行表示:开始于 clips[i][0] 并于 clips[i][1] 结束。我们甚至可以对这些片段自由地再剪辑,例如片段 [0, 7] 可以剪切成 [0, 1] + [1, 3] + [3, 7] 三部分。
我们需要将这些片段进行再剪辑,并将剪辑后的内容拼接成覆盖整个运动过程的片段([0, T])。返回所需片段的最小数目,如果无法完成该任务,则返回 -1 。
示例:
输入:clips = [[0,2],[4,6],[8,10],[1,9],[1,5],[5,9]], T = 10
输出:3
解释:
我们选中 [0,2], [8,10], [1,9] 这三个片段。
然后,按下面的方案重制比赛片段:
将 [1,9] 再剪辑为 [1,2] + [2,8] + [8,9] 。
现在我们手上有 [0,2] + [2,8] + [8,10],而这些涵盖了整场比赛 [0, 10]。
提示:
1 <= clips.length <= 100
0 <= clips[i][0], clips[i][1] <= 100
0 <= T <= 100
思路:
- 本题使用dp,先对区间从小到大排序,我想到的一个状态转移方程为:f[end] = min(f[start] + 1, f[end]) ,f[0] = 0,其中start、end分别对应当前处理区间的起止点。需要注意的是,每次更新 f[end] 后需要对区间 [start, end - 1] 的所有点进行更新。
- 使用贪心,每次找到一个最远的能够和之前的终点衔接起来的终点,复杂度O(n)
1 bool cmp(vector<int> &a,vector<int> &b){ 2 if(a[0]==b[0])return a[1]<b[1]; 3 return a[0]<b[0]; 4 } 5 class Solution { 6 public: 7 //贪心 8 int dp[110]; 9 int videoStitching(vector<vector<int>>& clips, int T) { 10 sort(clips.begin(),clips.end(),cmp); 11 int n=clips.size(); 12 if(clips[0][0]>0)return -1; 13 int i=0,pre=0,ans=0; 14 while(i<n){ 15 int ma=-1; 16 while(i<n&&clips[i][0]<=pre){ 17 ma=max(ma,clips[i][1]); i++; 18 if(ma>=T)return ans+1; 19 } 20 if(ma==-1)return -1; 21 ans++; pre=ma; 22 } 23 return -1; 24 } 25 };
1 bool cmp(vector<int> &a,vector<int> &b){ 2 if(a[0]==b[0])return a[1]<b[1]; 3 return a[0]<b[0]; 4 } 5 class Solution { 6 public: 7 int dp[110]; 8 int videoStitching(vector<vector<int>>& clips, int T) { 9 sort(clips.begin(),clips.end(),cmp); 10 int n=clips.size(); 11 if(clips[0][0]>0)return -1; 12 memset(dp,0x3f,sizeof(dp)); 13 dp[0]=0; 14 for(int i=0;i<n;i++){ 15 dp[clips[i][1]]=min(dp[clips[i][1]],dp[clips[i][0]]+1); 16 for(int j=clips[i][0];j<clips[i][1];j++)dp[j]=min(dp[j],dp[clips[i][1]]); 17 } 18 if(dp[T]==0x3f3f3f3f)return -1; 19 return dp[T]; 20 } 21 };