【问题标题】:How do you look through arrays more efficiently? Javascript [closed]如何更有效地查看数组? Javascript [关闭]
【发布时间】:2021-05-27 10:56:47
【问题描述】:

我一直在做很多关于 codility 的实践测试,虽然我所有的解决方案都有效,但它们总是有隐藏的压力测试,其中包括大量数组,例如以下代码需要获取数组 A 并找到最小的正数从序列中丢失。

例如:给定 A = [1, 3, 6, 4, 1, 2],函数应该返回 5。5 是 i 的值,它在循环中递增。只要在数组中找不到索引i,函数就会返回。

它可以正常工作,但 codility 使用 1-100,000 数组对其进行了测试,并在 6 秒限制时超时。由于同样的原因,我在练习测试中的大部分代码往往会失败。非常感谢任何帮助。

console.log(solution([1, 3, 6, 4, 1, 2]));
function solution(A) {
    let i = 0
    for (i = 1; i <= A.length ; i++){
        if(A.includes(i) == false){
            return i
        }
    }
    return i
}

【问题讨论】:

  • 您目前有一个 O(n²) 实现。您是否尝试过使用SetsMaps

标签: javascript arrays loops


【解决方案1】:

没有办法在O(n) 以内查看N 项目,这就是您正在做的事情。问题是您也在查看数组 N 次 - 这意味着您运行了 N*N 次并且可以改进。

改进此方法的最“典型”方法是使用Set 或类似的数据结构,并以摊销(通常)恒定时间访问元素。在你的情况下,这看起来像:

console.log(solution([1, 3, 6, 4, 1, 2]))
function solution(A) {
    // build existing elements, in O(N)
    const values = new Set(A)
    let i = 0
    for (i = 1; i <= A.length; i++){
        if(!values.has(i)){
            return i
        }
    }
    return i
}

这运行在O(N)(创建集合)+O(N) 迭代数组并每次执行恒定时间的工作。

【讨论】:

  • 我不知道创建 Set 本身就是 O(N) - 如果是这样,那就大大简化了事情!
  • @NiettheDarkAbsol 公平地说,ECMAScript 规范没有做出这种保证,它是一个实现细节。在实践中,Chrome、Firefox 和 Safari(嗯,V8、SpiderMoney 和 JSC)都使用HashMaps 来实现它们的集合。假设一个好的散列函数(在这种情况下很容易,只需 % 假设数字“合理”分布)这将导致 O(1) 插入 amortized 这意味着 O(N) 用于创建集合。
  • 另外,有趣的历史背景是wiki.mozilla.org/User:Jorend/Deterministic_hash_tables,Chromium 的 OrderedHashTable 就是基于它。为了完整起见,这里是使用的“端点”source.chromium.org/chromium/chromium/src/+/main:v8/src/…
【解决方案2】:

您的代码针对数组中的每个项目循环遍历数组中的每个项目。这给出了O(n^2) 的最坏情况运行时间。如果您对数组进行排序,然后遍历它以查找任何缺失的数字,您可以获得更好的结果。

function compareNumeric(a,b) {
    return a - b;
}

function solution(A) {
    A.sort(compareNumeric);
    let expect = 0;
    for( let i=0; i<A.length; i++) {
        if( A[i] > expect+1) return expect+1;
        if( A[i] === expect+1) expect++;
    }
    return expect+1;
}

console.time('simple');
console.log(solution([1, 3, 6, 4, 1, 2]));
console.timeEnd('simple');

// worst-case: all numbers from 1-1M exist but are randomly shuffled in the array
const bigArray = Array.from({length:1000000},(_,i)=>i+1);
function shuffle(a) {
    // credit: https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array
    for (let i = a.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [a[i], a[j]] = [a[j], a[i]];
    }
    return a;
}
shuffle(bigArray);
console.time('worst-case');
console.log(solution(bigArray));
console.timeEnd('worst-case');

这将为您提供O(n log n) 的运行时间,据我所知应该是最快的解决方案。

【讨论】:

    【解决方案3】:

    请检查这两个解决方案,它需要 O(n * log n) 或 O(n) 的时间复杂度,所以它会比以前的工作快得多。

    const arrayGenerator = (len) => {
      const array = [];
      for(let i = 0; i < len; i ++) {
        array.push(Math.floor(Math.random() * len) + 1);  
      }
      return array;
    }
    
    function sort_array_solution(A) {    
        A.map(a=>a).sort((a, b)=>a - b)    
        let ans = 1;
        for(let i = 0; i < A.length; i ++) {
          if(A[i] < ans) continue;
          if(A[i] > ans) return ans;
          ans ++;
        }
        return ans;
    }
    
    function object_key_solution(A) {    
        const obj = {}
        
        for(let i = 0; i < A.length; i ++) {
          obj[A[i]] = 1;
        }        
        
        for(let ans = 1; ; ans ++) {
          if(!obj.hasOwnProperty(ans)) return ans;      
          ans ++;
        }    
        return ans;
    }
    
    
    console.log(sort_array_solution([1,2]))
    console.log(object_key_solution([1,2]))
    
    const arr = arrayGenerator(10);
    console.log(sort_array_solution(arr))
    console.log(object_key_solution(arr))
    
    const arr1 = arrayGenerator(100000);
    console.log(sort_array_solution(arr1))
    console.log(object_key_solution(arr1))

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-22
      • 2014-04-13
      • 2016-05-11
      • 2019-05-12
      • 1970-01-01
      • 1970-01-01
      • 2020-03-07
      • 1970-01-01
      相关资源
      最近更新 更多