【发布时间】:2014-03-05 16:45:13
【问题描述】:
我目前正在跟踪视频的用户播放时间,并试图确定用户观看视频的百分比。我已经将问题概括为给定一系列可能重叠的数字范围,如何将它们组合成一系列不重叠的数字范围(即转换“0-10、5-15、30-45、20-25”变成“0-15, 20-25, 30-45”。
我有一个相对冗长的解决方案,其前提是如果对数字范围进行了排序,那么将两个相邻的数字范围组合起来是相对简单的(如果它们重叠或者它们保持分离,则将它们组合起来)。因此,我们首先对数字范围进行排序,然后遍历范围并将它们组合起来。
由于排序是最坏情况 O(nlgn),这意味着我的解决方案应该是 O(nlgn),我想知道是否有人知道该问题的 O(n) 解决方案?
var testcase = [
[0, 30], [40, 50], [5, 15], [70, 95], [45, 75], [0, 10],
[110, 115], [115, 120], [140, 175], [125, 160]
];
//sorts the array in ascending order (based on first element)
//if the first elements are the same, order based on second element (prioritising elements that are bigger)
testcase.sort(function(a, b) {
if (a[0] !== b[0]) return a[0] - b[0];
return b[1] - a[1]
})
function evaluate(a, b) {
var result = [];
//tests that the array is sorted properly
if ((a[0] > b[0]) || ((a[0] === b[0] ) && (a[1] < b[1]))) throw new Error('Array not sorted properly');
//if a and b do not overlap, then push both in the result
if(b[0] > a[1]) {
result.push(a, b);
}
//if a and b overlap
else {
var newElement = [a[0], Math.max(a[1], b[1])];
result.push(newElement);
}
return result;
}
console.log(testcase)
var combinedArr = [testcase[0]];
for (var i = 1; i < testcase.length; i++) {
var popped = combinedArr.pop();
combinedArr = combinedArr.concat(evaluate(popped, testcase[i]));
}
console.log(combinedArr);
【问题讨论】:
-
问题的规模有多大?似乎每个列表中的元素不会超过十几个(根据问题的描述,如果我错了,请纠正我)。对于这么小的尺寸,渐近复杂度几乎没有什么意义,而且插入排序,也就是纸上的 O(n^2),不太可能比其他排序技术获得更好的性能。
-
另外
sorting is worst case O(nlgn)- 这取决于实现的排序算法。例如,快速排序有 O(n^2) 最坏情况,而其他(例如合并排序)有 O(nlogn)。 -
不,那是不可能的。如果您假设您的输入未排序,并且希望您的输出升序,那么您将无法绕过排序。
-
@Bergi:如果输出的顺序无关紧要怎么办?
-
@amit 问题的规模可能不大,并且同意性能提升不大。话虽如此,我想借此机会提高我对算法的了解,因此想看看SO专家是否有任何提示。
标签: javascript algorithm time-complexity