【问题标题】:How to solve CountDistinctSlices codility question如何解决 CountDistinctSlices 代码性问题
【发布时间】:2020-11-07 14:17:06
【问题描述】:

我正在尝试“CountDistinctSlices”的代码问题。我尽我最大的努力得分 30%,所以我试着去寻找这样做的人以获得洞察力。基本上我没有得到答案是使用初始化的seen 数组(和M 就此而言)以及它是如何使用的,知道它的人可以引导我完成这段代码。

这是我找到的答案,没有解释

function solution(M, A) {
    // write your code in JavaScript (Node.js 8.9.4)
    let sum = 0;
    let front = 0;
    let back = 0;
    const seen = new Array(M+1).fill(false);
    while (front < A.length && back < A.length){
        while (front < A.length && seen[A[front]] !== true){
            sum += (front-back+1);
            seen[A[front]] = true;
            front += 1;
        }
        while (A[back] !== A[front]){
            seen[A[back]] = false;
            back += 1;
        }
        seen[A[back]] = false;
        back += 1;
    }           
    return Math.min(sum, 1000000000);
}

这是完整的问题

一个整数 M 和一个由 N 个非负数组成的非空数组 A 给出整数。数组 A 中的所有整数都小于或等于 M.

一对整数 (P, Q),使得 0 ≤ P ≤ Q

例如,考虑整数 M = 6 和数组 A,这样: A[0] = 3 A[1] = 4 A[2] = 5 A[3] = 5 A[4] = 2

正好有九个不同的切片:(0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2), (3, 3), (3, 4) 和 (4, 4)。

目标是计算不同切片的数量。

写一个函数:

function solution(M, A);

给定一个整数 M 和一个由 N 组成的非空数组 A 整数,返回不同切片的数量。

如果不同切片的数量大于 1,000,000,000,则 函数应该返回 1,000,000,000。

例如,给定整数 M = 6 和数组 A,这样:

A[0] = 3

A[1] = 4

A[2] = 5

A[3] = 5

A[4] = 2

该函数应返回 9,如上所述。

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

    N is an integer within the range [1..100,000];
    M is an integer within the range [0..100,000];
    each element of array A is an integer within the range [0..M].

【问题讨论】:

标签: javascript algorithm


【解决方案1】:

让我们先来看看算法:

  • 您首先从头开始并遍历,直到找到重复项。现在你有一个range = [ back - front ]

  • 代码将此范围称为 [back, front],其中“back”是开始,“front”是您的移动指针。 在这个范围内有多少个不同的切片?有大小为 1, 2, .... 前 - 后 + 1 的切片,所以是 sum = 1 + 2 + 3 + ... [front - back + 1]

  • 既然你遇到了重复,你应该怎么做?要理解,让我们以问题中的示例为例:[3,4,5,5,2]。现在front 达到5。现在我们应该将back 指针指向5,但同时从集合中删除元素3, 4, 5,因为这些元素可能出现在当前前面之后。所以back 到了5,而front 是当前指向的。

    让我们再举一个例子 [1,2,1] ,因为这个 front 将在索引 2 处到达 1 因为这是找到的第一个重复项。现在back应该去哪里?它应该到达2,因为当您在移动back 指针时删除集合中的元素时,这将是集合不会有任何重复的位置。

  • 这样做直到front 到达数组的末尾。

您对seen的问题

如何在数组中找到重复项?您可以使用 Set 也可以使用布尔数组。我认为M 在这个问题中的唯一目的是指定数组中的元素可以具有的最大值。所以代码使用了一个大小为M的布尔数组。

如果你使用布尔数组,一旦你找到一个值元素,比如v,你可以直接说boolean_arr[v] = true,这意味着它被“看到”了。

或者您可以使用一个集合并在需要时创建一个新的集合,而不必在每次找到重复项时都清除整个布尔数组 - 通过让 JavaScript 处理垃圾收集 - 如下所示(未完全测试):

function solution(M, A) {
    let sum = 0;
    let front = 0;
    let back = 0;
    let set = new Set();
    while (front < A.length) {
        while (front < A.length && !set.has(A[front])){
            sum += (front-back+1);
            set.add(A[front]);
            front += 1;
        }
        while (A[back] != A[front]) {
            set.delete(A[back]);
            back += 1;
        }
        set.delete(A[back]);
        back += 1;
    }           
    return Math.min(sum, 1000000000);
}

【讨论】:

  • 非常感谢清晰详细的解释,我学到了一些东西。
  • [1,2,1] 的解决方案失败。根据您的 alg 答案 4,但应该是 5:(0,0), (1,1), (2,2), (0,1), (1,2)。问题是您的 alg 错误地设置回前面,从而忽略了切片的一部分。
  • @fade2black 你是对的!我修改了代码,还添加了解释。
猜你喜欢
  • 2020-03-10
  • 2021-03-01
  • 2021-08-05
  • 1970-01-01
  • 2013-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-19
相关资源
最近更新 更多