[英]Time and space complexity of counting number of substrings with exactly K unique characters?
[英]Time Space Complexity of k smallest of unsorted array
我在面试中解决了这个问题,但我不知道时空复杂度是什么。
以下解决方案的时空复杂度是多少?
// Ordered Map Method
function orderedMapFrequency(array) {
const map = {};
for (let i = 0; i < array.length; i++) {
if (!map[array[i]]) {
map[array[i]] = 1;
} else {
map[array[i]]++;
}
}
return map;
}
function kSmallest(arr, k) {
let map = orderedMapFrequency(arr);
let frequencies = 0;
for (const [key, val] of Object.entries(map)) {
frequencies = frequencies + val;
if (frequencies >= k) {
return key;
}
}
}
// variables
let input;
let k;
input = [7, 10, 4, 3, 20, 15];
k = 3;
console.log(kSmallest(input, k)); // 7
input = [7, 10, 4, 3, 20, 15];
k = 4;
console.log(kSmallest(input, k)); // 10
input = [12, 3, 5, 7, 19];
k = 2;
console.log(kSmallest(input, k)); // 5
input = [7, 0, 25, 6, 16, 17, 0];
k = 3;
console.log(kSmallest(input, k)); // 6
我认为它可能是 O(log(n)) 还是简单的 O(n)?
空间复杂度
在)
时间复杂度
O(NlogN)
将条目插入有序映射是 O(logN),因此从数组创建这样的有序映射是 O(NlogN)。 因此,您的orderedMapFrequency
是O(NlogN)。 通过遍历有序映射找到第 k 个最小元素是 O(k),这取决于有序映射的创建。 因此总的时间复杂度是 O(NlogN)。
附录
您可以在此处查看以找到具有更好时间复杂度的解决方案。
有趣的是,Javascript 中的 Object {}
充当整数键的有序映射,请参阅ES6 是否为对象属性引入了定义良好的枚举顺序? :
整数索引(如果适用),按升序排列。
您的解决方案使用 JavaScript 对象的一个特性:在调用Object.entries
函数时,索引的十进制表示键将按排序顺序迭代。
从规范中我们只能了解到设置和获取对象属性必须具有亚线性时间复杂度(参见Javascript ES6 计算/集合时间复杂度),因此这些操作在恒定时间内运行并不是语言的绝对要求。
如果这些在时间上是恒定的,并且对这些属性的迭代将花费线性时间,那么我们将找到一种在线性时间内对数字进行排序的方法,这是不可能的,除非应用一些限制,这将允许非比较排序算法,例如作为基数排序算法。
并且这里有一些限制:对象键仅在这些数字是 0 到 2 31 -1 范围内的整数时才按其数字顺序迭代。 所以这不适用于:
这些键将按照插入的顺序在其他数字之后迭代(对于根本不是数字表示的键也会发生这种情况)。 因此,当发生此类情况时,您的解决方案可能会产生错误的结果。
这是在稍微修改的输入上运行的代码,这些输入违反了上述条件之一:
let input, k; input = [7, 10, 4, -3, 20, 15]; // Notice -3 console.log(kSmallest(input, 3)); // 10 (should be 7) input = [7, 10, 4, 3.1, 20, 15]; // Notice 3.1 console.log(kSmallest(input, 4)); // 15 (should be 10) input = [12000000000, 3000000000, 5000000000, 7000000000, 19000000000]; // Big numbers console.log(kSmallest(input, 2)); // 12000000000 (should be 5000000000) // Your functions (unchanged) function orderedMapFrequency(array) { const map = {}; for (let i = 0; i < array.length; i++) { if (!map[array[i]]) { map[array[i]] = 1; } else { map[array[i]]++; } } return map; } function kSmallest(arr, k) { let map = orderedMapFrequency(arr); let frequencies = 0; for (const [key, val] of Object.entries(map)) { frequencies = frequencies + val; if (frequencies >= k) { return key; } } }
如您所见,输出并不是您所期望的k -smallest。
如果目标是让算法在这些情况下也能正常工作,那么您就不能再依赖 JavaScript 对象的这种特定行为以及Object.entries
等函数的属性迭代顺序,您将不得不提出一个明确的编写的算法(例如使用堆数据结构),如果做得好,它将具有 O(nlogk) 时间复杂度。
至于算法的时间复杂度:它取决于 JavaScript 引擎,但在为对象键集合上的 get/set 操作提供接近恒定的时间复杂度方面,似乎很多都做得很好。 所以这意味着您的解决方案在实践中提供了 O(n) 时间复杂度。 但:
空间复杂度是微不足道的:O(n)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.