【问题标题】:Codility Leader Algorithm in JavaScriptJavaScript 中的 Codility Leader 算法
【发布时间】:2019-12-28 01:44:47
【问题描述】:

我正在尝试 JavaScript 中的 Codility 'Leader' 问题。

问题如下:

给出了一个由N 整数组成的数组A。数组A的支配者是出现在A的一半以上元素中的值。

例如,考虑数组A 这样

A[0] = 3    A[1] = 4    A[2] =  3
A[3] = 2    A[4] = 3    A[5] = -1
A[6] = 3    A[7] = 3

A 的支配者是 3,因为它出现在 A 的 8 个元素中的 5 个中(即在索引为 0、2、4、6 和 7 的 > 中),并且 5 超过一半8 个。

编写一个函数function solution(A);,给定一个由N 整数组成的数组A,返回数组A 中出现A 的支配者的任何元素的索引。如果数组 A 没有支配者,该函数应该返回 -1。

例如,给定数组A,这样

A[0] = 3    A[1] = 4    A[2] =  3
A[3] = 2    A[4] = 3    A[5] = -1
A[6] = 3    A[7] = 3

该函数可能返回 0、2、4、6 或 7,如上所述。

为以下假设编写一个有效的算法:

N[0..100,000]; 范围内的整数 并且数组A的每个元素都是[−2,147,483,648..2,147,483,647]范围内的整数。

我的答案如下:

function solution(A) {
    const length = A.length
    if (length > 100000) return -1
    const counters = new Array(length).fill(0)
    const negativeCounters = new Array(length).fill(0)
    for (i=0; i < length; i++){
        if (A[i] < -2147483648 || A[i] > 2147483647) return -1
        if (A[i] > -1){
            counters[A[i]] = counters[A[i]] + 1
            if (counters[A[i]] > (length / 2)) return i
        } else {
            negativeCounters[A[i] * -1]  =  negativeCounters[A[i] * -1] + 1
            if (negativeCounters[A[i] * -1] > (length / 2)) return i
        }
    }
    return -1
}

尽管我尝试了各种成功的输入,但它未能通过正确性测试。 Codility 评估没有列出测试输入,所以我找不到破坏算法的输入。

谁能发现问题?

【问题讨论】:

  • 问题:如果数组像[0..1],那么最大长度是2。如果数组像[0..100,000];,最大长度不应该是100,001吗?你在第一个 if 中限制了这种情况
  • 失败案例有没有给你任何输出?您可能内存不足,分配了两个大小数组,每个数组可能 100K
  • @Gonzalo.- 哈哈我也在担心同样的事情,我认为不是因为问题指定在 0 到 100000 成员范围内,所以 100001 会导致返回。
  • @sinanspd 有一些输出:在 SMALL_TEST .. 错误答案,得到 -1,但支配者存在,例如在位置 8,在 SMALL_NON_DENOMINATOR.. 得到 -1,但支配者存在,例如在位置 0,在 MEDIUM_RANDOM 上(使用支配者进行随机测试,N = 10,000).. 得到 -1,但支配者存在,例如在位置 9。这是问题的症结所在,我的输出不是很有帮助
  • @NicoSchertler 这在 JavaScript 中运行良好:a = new Array(3); a[2147483647] = 4; console.log(a.length, a[2147483647]) 因为数组在 JS 中是关联的。但是,尝试将尚未初始化为零的值递增可能效果不佳。

标签: javascript algorithm


【解决方案1】:

与某些 cmets 和一个答案相反,实际上在 JavaScript 中使用一组计数器可以正常工作。这是因为 JavaScript 中的数组是关联对象。您的代码的一个问题是它无法将键/索引大于初始计数器数组长度的计数器初始化为零。

以下代码在 Codility 的所有测量中均获得 100% 的分数:

function solution(A) {
    const arr = []
    for (let i=0; i<A.length; i++){
      if (!arr[A[i]])
        arr[A[i]] = 1
      else
        arr[A[i]]++
      if (arr[A[i]] > A.length/2)
        return i
    }
    return -1
}

【讨论】:

  • 啊.. 哦。当然,我没有想到我将数组长度视为整数的边界......非常愚蠢。太棒了,非常感谢 :) 我希望这种方法能奏效
【解决方案2】:

您不应该使用具有如此大范围值的数组(正值数组的长度需要为 2,147,483,648)。您应该使用地图或在 js 中您可以使用对象。我一起破解了一些东西,不是很优雅,但它通过了所有测试:

function solution(A) {
    const map = {}
    for (let i = 0; i < A.length; i++) {
        const key = '' + A[i]
        map[key] = key in map ? map[key] + 1 : 1
        if (map[key] > A.length / 2)
            return i
    }
    return -1
}

【讨论】:

  • 这对于 JavaScript 来说是不正确的。请看我的回答。
  • @גלעדברקן 好吧,我仍然得到 100%。如果我说let arr = []; arr[15] = 12; console.log(arr);,它将打印出 16 个值,而arr.length 是 16。所以它不是完全错误的。也许它没有使用所有的存储空间,但我对长度是正确的。
  • 感觉不干净。长度不对。如果你想遍历所有定义的值,你会怎么做?也许它适用于这种情况,但我不喜欢它。
  • 我同意。它不干净,一般来说,它似乎是在盗用数组。我试图指出,在这种情况下,它可能不是 OP 代码失败的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-25
  • 1970-01-01
  • 2013-01-03
  • 1970-01-01
  • 2020-09-19
相关资源
最近更新 更多