Create array with length n, initialize all values with 0 besides one which index matches a certain condition, in O(1)?

空扰寡人 提交于 2020-03-05 03:24:08

问题


I want to create an array of type number with length n. All values inside the array should be 0 except the one which index matches a condition.

Thats how i currently do it:

const data: number[] = [];
for (let i = 0; i < n; i++) {
  if (i === someIndex) {
    data.push(someNumber);
  } else {
    data.push(0);
  }
}

So lets say n = 4, someIndex = 2, someNumber = 4 would result in the array [0, 0, 4, 0].

Is there a way to do it in O(1) instead of O(n)?


回答1:


You need to assign n values, and so there is that amount of work to do. The work increases linearly with increasing n.

Having said that, you can hope to make your code a bit faster by making use of .fill:

const data: number[] = Array(n).fill(0);
data[someIndex] = someNumber;

But don't be mistaken; this is still O(n): .fill may be faster, but it still requires to fill the whole array with zeroes, which means a corresponding size of memory needs to be initialised, so that operation has linear time complexity.

If however you drop the requirement that zeroes need to be assigned, then you can only store the someNumber:

const data: number[] = Array(n);
data[someIndex] = someNumber;

This way you actually do not allocate the memory for the whole array, so this code snippet runs in constant time. Any access to an index different from someIndex will give you a value of undefined. You may trap that condition and translate that to a zero on-the-fly:

let value = i in data ? data[i] : 0;

Obviously, if you are going to access all indices of the array like that, you'll have again a linear time complexity.




回答2:


Creating an array of size n in O(1) time is theoretically possible depending on implementation details - in principle, if an array is implemented as a hashtable then its length property can be set without allocating or initialising space for all of its elements. The ECMAScript specification for the Array(n) constructor doesn't mandate that Array(n) should do anything which necessarily takes more than O(1) time, although it also doesn't mandate that the time complexity is O(1).

In practice, Array(n)'s time complexity depends on the browser, though verifying this is a bit tricky. The performance.now() function can be used to measure the time elapsed between the start and end of a computation, but the precision of this function is artificially reduced in many browsers to protect against CPU-timing attacks like Spectre. To get around this, we can call the constructor repetitions times, and then divide the time elapsed by repetitions to get a more precise measurement per constructor call.

My timing code is below:

function timeArray(n, repetitions=100000) {
    var startTime = performance.now();
    for(var i = 0; i < repetitions; ++i) {
        var arr = Array(n);
        arr[n-1] = 'foo';
    }
    var endTime = performance.now();
    return (endTime - startTime) / repetitions;
}

for(var n = 10000; n <= 1000000; n += 10000) {
    console.log(n, timeArray(n));
}

Here's my results from Google Chrome (version 74) and Firefox (version 72); on Chrome the performance is clearly O(n) and on Firefox it's clearly O(1) with a quite consistent time of about 0.01ms on my machine.

I measured using repetitions = 1000 on Chrome, and repetitions = 100000 on Firefox, to get accurate enough results within a reasonable time.

Another option proposed by @M.Dietz in the comments is to declare the array like var arr = []; and then assign at some index (e.g. arr[n-1] = 'foo';). This turns out to take O(1) time on both Chrome and Firefox, both consistently under one nanosecond:

That suggests the version using [] is better to use than the version using Array(n), but still the specification doesn't mandate that this should take O(1) time, so there may be other browsers where this version takes O(n) time. If anybody gets different results on another browser (or another version of one of these browsers) then please do add a comment.



来源:https://stackoverflow.com/questions/59753659/create-array-with-length-n-initialize-all-values-with-0-besides-one-which-index

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!