1024. 视频拼接
你将会获得一系列视频片段,这些片段来自于一项持续时长为 time
秒的体育赛事。这些片段可能有所重叠,也可能长度不一。
使用数组 clips
描述所有的视频片段,其中 clips[i] = [starti, endi]
表示:某个视频片段开始于 starti
并于 endi
结束。
甚至可以对这些片段自由地再剪辑:
[0, 7]
可以剪切成 [0, 1] + [1, 3] + [3, 7]
三部分。我们需要将这些片段进行再剪辑,并将剪辑后的内容拼接成覆盖整个运动过程的片段([0, time]
)。返回所需片段的最小数目,如果无法完成该任务,则返回 -1
。
示例 1:
输入:clips = [[0,2],[4,6],[8,10],[1,9],[1,5],[5,9]], time = 10 输出:3 解释: 选中 [0,2], [8,10], [1,9] 这三个片段。 然后,按下面的方案重制比赛片段: 将 [1,9] 再剪辑为 [1,2] + [2,8] + [8,9] 。 现在手上的片段为 [0,2] + [2,8] + [8,10],而这些覆盖了整场比赛 [0, 10]。
示例 2:
输入:clips = [[0,1],[1,2]], time = 5 输出:-1 解释: 无法只用 [0,1] 和 [1,2] 覆盖 [0,5] 的整个过程。
示例 3:
输入:clips = [[0,1],[6,8],[0,2],[5,6],[0,4],[0,3],[6,7],[1,3],[4,7],[1,4],[2,5],[2,6],[3,4],[4,5],[5,7],[6,9]], time = 9 输出:3 解释: 选取片段 [0,4], [4,7] 和 [6,9] 。
提示:
1 <= clips.length <= 100
0 <= starti <= endi <= 100
1 <= time <= 100
原站题解
python3 解法, 执行用时: 44 ms, 内存消耗: 14.9 MB, 提交时间: 2022-12-11 12:30:21
class Solution: def videoStitching(self, clips: List[List[int]], time: int) -> int: dp = [0] + [float("inf")] * time for i in range(1, time + 1): for aj, bj in clips: if aj < i <= bj: dp[i] = min(dp[i], dp[aj] + 1) return -1 if dp[time] == float("inf") else dp[time]
golang 解法, 执行用时: 4 ms, 内存消耗: 2 MB, 提交时间: 2022-12-11 12:30:09
func videoStitching(clips [][]int, time int) int { const inf = math.MaxInt64 - 1 dp := make([]int, time+1) for i := range dp { dp[i] = inf } dp[0] = 0 for i := 1; i <= time; i++ { for _, c := range clips { l, r := c[0], c[1] // 若能剪出子区间 [l,i],则可以从 dp[l] 转移到 dp[i] if l < i && i <= r && dp[l]+1 < dp[i] { dp[i] = dp[l] + 1 } } } if dp[time] == inf { return -1 } return dp[time] }
java 解法, 执行用时: 2 ms, 内存消耗: 39 MB, 提交时间: 2022-12-11 12:29:57
class Solution { public int videoStitching(int[][] clips, int time) { int[] dp = new int[time + 1]; Arrays.fill(dp, Integer.MAX_VALUE - 1); dp[0] = 0; for (int i = 1; i <= time; i++) { for (int[] clip : clips) { if (clip[0] < i && i <= clip[1]) { dp[i] = Math.min(dp[i], dp[clip[0]] + 1); } } } return dp[time] == Integer.MAX_VALUE - 1 ? -1 : dp[time]; } }
cpp 解法, 执行用时: 4 ms, 内存消耗: 7.5 MB, 提交时间: 2022-12-11 12:29:45
// 动态规划,dp[i] 表示将区间 [0,i) 覆盖所需的最少子区间的数量 class Solution { public: int videoStitching(vector<vector<int>>& clips, int time) { vector<int> dp(time + 1, INT_MAX - 1); dp[0] = 0; for (int i = 1; i <= time; i++) { for (auto& it : clips) { if (it[0] < i && i <= it[1]) { dp[i] = min(dp[i], dp[it[0]] + 1); } } } return dp[time] == INT_MAX - 1 ? -1 : dp[time]; } };
python3 解法, 执行用时: 36 ms, 内存消耗: 14.9 MB, 提交时间: 2022-12-11 12:28:15
class Solution: def videoStitching(self, clips: List[List[int]], time: int) -> int: maxn = [0] * time last = ret = pre = 0 for a, b in clips: if a < time: maxn[a] = max(maxn[a], b) for i in range(time): last = max(last, maxn[i]) if i == last: return -1 if i == pre: ret += 1 pre = last return ret
golang 解法, 执行用时: 0 ms, 内存消耗: 2 MB, 提交时间: 2022-12-11 12:28:02
func videoStitching(clips [][]int, time int) (ans int) { maxn := make([]int, time) last, pre := 0, 0 for _, c := range clips { l, r := c[0], c[1] if l < time && r > maxn[l] { maxn[l] = r } } for i, v := range maxn { if v > last { last = v } if i == last { return -1 } if i == pre { ans++ pre = last } } return }
java 解法, 执行用时: 0 ms, 内存消耗: 39.4 MB, 提交时间: 2022-12-11 12:27:50
class Solution { public int videoStitching(int[][] clips, int time) { int[] maxn = new int[time]; int last = 0, ret = 0, pre = 0; for (int[] clip : clips) { if (clip[0] < time) { maxn[clip[0]] = Math.max(maxn[clip[0]], clip[1]); } } for (int i = 0; i < time; i++) { last = Math.max(last, maxn[i]); if (i == last) { return -1; } if (i == pre) { ret++; pre = last; } } return ret; } }
cpp 解法, 执行用时: 0 ms, 内存消耗: 7.5 MB, 提交时间: 2022-12-11 12:27:36
// 贪心算法 // 对于所有左端点相同的子区间,其右端点越远越有利。且最佳方案中不可能出现两个左端点相同的子区间。 // 于是我们预处理所有的子区间,对于每一个位置 i,我们记录以其为左端点的子区间中最远的右端点,记为maxn[i]。 class Solution { public: int videoStitching(vector<vector<int>>& clips, int time) { vector<int> maxn(time); int last = 0, ret = 0, pre = 0; for (vector<int>& it : clips) { if (it[0] < time) { maxn[it[0]] = max(maxn[it[0]], it[1]); } } for (int i = 0; i < time; i++) { last = max(last, maxn[i]); if (i == last) { return -1; } if (i == pre) { ret++; pre = last; } } return ret; } };