【问题标题】:MaxCounters (lesson 4 in codility) - 100% correctness but 60% on efficiency, why?MaxCounters(代码第 4 课)- 100% 正确,但效率为 60%,为什么?
【发布时间】:2022-06-27 01:23:08
【问题描述】:

Link to the problem 简而言之:N 是一个整数,表示计数器的数量和允许的最大计数器。 A 是一个数组,表示在特定计数器上完成的操作(例如,如果 A[0] 为 1,N 为 3,我们需要将 1 加到 'counters' 数组[0])如果 A 中的元素为 N+1,计数器中的所有元素都应更改为计数器数组中的最大数字。 我提交了自己编写的代码,但性能只有 60%,这是为什么呢?下次我应该以什么方式解决问题以提高效率?我该如何改进?

function solution(N,A){

let counters = Array(N).fill(0);
let maxCounter = 0;
for(i=0;i<A.length;i++){
    if(A[i]<=N){
        counters[A[i]-1]++
        if(counters[A[i]-1]>maxCounter){maxCounter = counters[A[i]-1]};
    }
    else if(A[i]===N+1){
        counters = Array(N).fill(maxCounter)
    }
}
return counters

}

编辑:我不知道这个网站不是针对代码改进的问题,谢谢,我会在其他地方问。

【问题讨论】:

  • 这更适合在 reddit 上发帖,stackoverflow 并不是真正适合这类问题的(至少我不这么认为)
  • 我们修复了损坏的代码,如果您有想要改进的工作代码,您需要转到Code Review

标签: javascript


【解决方案1】:

一个可能的改进是,当您需要用新的最大计数器填充整个数组时,不要为此创建一个全新的数组 - 而是更改现有数组。

else if(A[i]===N+1){
    counters.fill(maxCounter)
}

如果有很多计数器,这可能会产生很大的影响。

【讨论】:

  • 它有一点帮助,但我仍然获得 60% 的相同性能分数。
【解决方案2】:

这是一个使用对象的解决方案,它只会生成一次实际的数组(在应用所有操作之后)。

“跟踪器”对象只会保存那些有操作的计数器的索引和值。假设 N(即“num”个计数器)为 50,000,但只有 5,000 个计数器在 A(即“arr”数组)中有显式操作,只有这 5,000 个元素将被跟踪(使用“跟踪器”对象)。

代码片段

// alternative solution using object
const counterOps = (num, arr) => {
  // the "tracker" object we will use to populate the result array
  const tracker = {};
  
  // when "num+1" to reset all elements to "max", then
  // the "max" value is stored in "lastMaxSet"
  let lastMaxSet = 0;
  
  // helper method to get current max from "tracker"
  const getMax = obj => Math.max(...Object.values(obj));
  
  // helper method to "set" "all" values to "max"
  const setMax = obj => {
    lastMaxSet = getMax(obj);
    Object.keys(obj).forEach(k => obj[k] = lastMaxSet);
  };
  
  // iterate through "arr" and "apply" each "operation"
  arr.forEach(elt => {
    if (elt === num + 1) {
      // "reset to max" operation is applied
      setMax(tracker);
    } else {
      // a particular counter is incremented
      const k = elt - 1;
      tracker[k] ??= lastMaxSet;
      tracker[k]++;
    }
  });
  
  // the "tracker" object is used to generate
  // the result-array on-the-fly
  return [...Array(num).fill(lastMaxSet)].map(
    (val, idx) => idx in tracker ? tracker[idx] : val
  );
};

console.log(counterOps(5, [3, 4, 4, 6, 1, 4, 4]));
.as-console-wrapper { max-height: 100% !important; top: 0 }

如果有帮助(性能方面),请尝试并分享反馈。

【讨论】:

    【解决方案3】:

    60% 效率得分是因为执行了超过10,000“max counter” 操作的最后两个测试用例。 https://app.codility.com/demo/results/trainingA86B4F-NDB/

    这些操作中的每一个都必须遍历counter 数组,该数组可能有多达100,000 元素。总共有 1 billion 写入,因此性能问题的原因很快就出现了。

    为了改善这一点并降低这个数字,我们可以消除不必要的连续 "max counter" 操作,例如,引入一个标志来表示 counter 数组是否已经达到最大值并且存在不需要从头再来一遍。

    示例代码:

    const solution = (n, arr) => {
      const counter = new Array(n).fill(0);
      let max = 0, counterMaxed = false;
    
      for (let curr of arr) {
        if (curr > n) {
          if (!counterMaxed) { counter.fill(max); counterMaxed = true; }
          continue;
        }
    
        curr--; counter[curr]++; counterMaxed = false;
        if (counter[curr] > max) { max = counter[curr]; }
      }
    
      return counter;
    };
    

    这得到了一个直 100% 分数:
    https://app.codility.com/demo/results/training3H48RM-6EG/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-17
      • 1970-01-01
      • 1970-01-01
      • 2015-06-18
      • 2019-04-16
      • 2014-02-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多