简体   繁体   中英

what is the time complexity of array.splice(…array.splice())

I was solving one of the leetcode question which is rotating array. I solve with O(N) by using two for loop but then my runtime was lower then this solution.

My solution: runtime 80ms

var rotate = function(nums, k) {

    let a = Array.from({length:nums.length})

    for (let i = 0; i < nums.length; i++) {
      a[(i + k) % nums.length] = nums[i];
    }
    for (let i = 0; i < nums.length; i++) {
      nums[i] = a[i];
    }


};

Other Solution: runtime 52ms

var rotate = function(nums, k) {
      return nums.splice(0,0,...nums.splice(nums.length - k))
};

how this is possible. As I know splice is O(N) and in this solution splice also is being used in the splice again. So this solution should be O(N2) and my solution should be faster then this?

Array#splice is O(n) because it can shift up to each array element per call. See: What's the time complexity of array.splice in Google Chrome?

In determining the time complexity of an algorithm, as long as each O(n) operation is in series and the number of O(n) operations is a constant factor (which are the case here), it's still O(n). O(n 2 ) is the consequence of nested loops; that is, for each n we perform another O(n) operation.

This code uses only two sequential calls to Array#splice along with an O(n) spread for a total of O(3n) which is equivalent to O(n).

"My runtime was slower" -- Time complexity and runtime are totally distinct things. Much of runtime rests on implementation details, fixed overhead expenses (constant factors) that are ignored by big O, how large LC's test cases are, the composition of the test cases, inaccuracies LC's test case measurement, etc. Use a benchmark under your own control on very large random inputs to be more certain. Two O(n) codes rarely exhibit identical performance characteristics--time complexity is only concerned with the rate of growth of an algorithm.

As for this particular comparison, keep in mind that builtin functions are highly optimized. I'm assuming this runs in NodeJS (V8), so many builtins are written in C++ (or Torque) (and V8 is not unique in this).

Implementing builtins natively at a lower-level means the memory is likely to be compact and regular so cache accesses benefit from locality , less pointer chasing, opportunities for stack allocation , etc. for loops in high-level code are harder to optimize. They involve index variables, performing comparisons, branching and so forth, all of which needs to be effectively translated to bytecode in a way that may be sub-optimal. In cases when the builtin implementation is in JS, the designers have done much work to make them as efficient as possible.

In Array#splice 's case, it's written in Torque which is translated to efficient assembly .

In your code, let a = Array.from({length:nums.length}) . Incurs allocation overhead for two objects.

In short: benchmark fairly, don't conflate complexity and speed, and use builtins whenever possible (use a profiler to determine rare cases when not to).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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