繁体   English   中英

k 最小未排序数组的时空复杂度

[英]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.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) 时间复杂度。 但:

  • 允许 JavaScript 实现为对象键集合上的 get/set 操作提供 O(logn) 时间复杂度,因此您的解决方案具有 O(nlogn) 时间复杂度。
  • 上述限制使得任何关于时间复杂度的陈述都没有意义。

空间复杂度是微不足道的:O(n)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM