繁体   English   中英

从数组中删除连续元素的最有效方法? 爪哇

[英]Most efficient way to remove consectuive elements from an array? Java

我试图以最有效的方式解决这个问题。

给定一个整数数组,继续删除三个连续的相同整数,直到数组中不再有三个连续的相同元素,并返回这些元素出现的次数。

例如 int[] {4,4,7,7,6,6,6,7,4} 将返回 3。当我们删除连续 6 的 int 数组时变为 {4,4,7,7,7,4}下一次迭代,连续的 7 被删除,我们剩​​下 {4,4,4} 等等。

int[] {3,4,4,5,5,3} 将返回 0。

我已经尝试了十几次使用不同的集合,但有人说我的代码需要很多操作,而且速度太慢。 所以我只想使用数组,但我被卡住了。 这是我的代码:

    public static int getNumberOfRepetitions(int[] arr) {

    int[] arr2 = new int[arr.length];
    int counter= 0;
    int index = 0;

    for (int x= 0;x<arr.length;x++) {
        if (x < arr.length - 2) {
            if (arr[x] == arr[x + 2] && arr[x] == arr[x + 2]) {
                counter++;
                x = x + 2;
                continue;
            }
            arr2[index] = arr[x];
            index++;
        }
        if (x < arr.length - counter * 3) {
            arr = arr2;
            arr2 = new int[arr.length];
            index = 0;
            x = -1;
        }
    }
    return counter;
}

该算法迭代一个数组并将项目添加到第二个数组,如果有连续元素,则添加到计数器并跳过它们。 在最后一次迭代中,arr 设置为 arr2 并且 for 循环应该重置。

到目前为止,我无法弄清楚如何终止代码,所以我得到了一个无限循环。 我是编程新手,希望得到任何帮助。

你的逻辑有几处错误。 这里没有指出每个人,而是一种新方法:

private static int getNumberOfRepetitions(int[] arr) {
    int[] arr2 = new int[arr.length];
    int counter= 0;
    int j = 0;
    for (int i : arr) {
        arr2[j++] = i;
        if (j > 2) {
            if (arr2[j - 1] == arr2[j - 2] && arr2[j - 1] == arr2[j - 3]) {
                counter++;
                j -= 3;
            }
        }
    }
    return counter;
}

在这里,我们将元素一个一个地添加到一个新数组中,并为该数组维护一个索引。 当新数组中有 3 个元素时,比较最后 3 个。如果它们相等,则将索引 ('j') 减 3。

有人告诉我,我的代码需要太多操作,而且速度太慢。

这是正确的,因为您实际上可以在不修改数组的情况下执行此操作。

由于这是一项需要您完成的作业,因此我将向您展示如何做到这一点,而无需编写任何代码。

  1. 将 counter 初始化为 0,并从数组的开头开始迭代。

  2. 找到下一个(第一个)三元组。
    如果没有找到,你就完成了,所以返回计数器值。

     start │ end │ │ 4,4,7,7,6,6,6,7,4
  3. 您找到了要删除的三元组,因此将计数器加 1。

  4. 比较周围的值。 首先比较前后的值。
    如果不同,请跳到第 7 步。

     start │ end │ │ 4,4,7,7,6,6,6,7,4 └───────┘ are they equal?
  5. 当周围的值相等时,级联三元组有两种可能性,一个是之前的额外值,一个是之后的额外值。
    如果之前/之后的额外值都与周围值不同,请跳到步骤 7。

     start start │ end │ end │ │ OR │ │ 4,4,7,7,6,6,6,7,4 4,7,6,6,6,7,7,4,4 └─┴───────┘ are they equal? └───────┴─┘ are they equal?
  6. 展开要移除的序列,然后返回步骤 3 重复级联搜索。

     start start │ end │ end │ │ OR │ │ 4,4,7,7,6,6,6,7,4 4,7,6,6,6,7,7,4,4
     start start │ end │ end │ │ OR │ │ 4,4,7,7,6,6,6,7,4 4,7,6,6,6,7,7,4,4 └─┴─────────────┘ └─────────────┴─┘ are they equal?
  7. 现在我们需要寻找一个更复杂的不相交三元组。

     12344433255666527 ││└┴┘││││││││││ simple triplet found (step 2-3) │└───┴┘││││││││ surrounding triplet found (step 4-6) │ │││└┴┘││ another simple triplet found │ │└┴───┘│ surrounding triplet found └──────┴──────┘ disjoint triplet found

    为此,我们需要跟踪删除的先前序列。

     ┌ prevStart │ ┌ prevEnd │ │ ┌ start │ │ │ ┌ end 12344433255666527 └──────┴──────┘ are they equal?

    如果前一个结束在新开始之前的 2 个位置,并且之前、之间和之后的 3 个值相等,那么我们找到了一个不相交的三元组。 展开要删除的序列以包括先前的序列、当前的序列和新的三元组,然后返回步骤 3 以重复级联搜索。

  8. 您现在已找到要删除的部分,并将计数器增加适当的次数,因此从end位置开始,返回步骤 2 以搜索下一个三元组。

如您所见,数组永远不会被修改,我们只是将索引值处理到数组中。 这需要更多的代码,而不是简单地修改数组并重试,但新代码运行得更快,因为我们不必复制数组元素。

祝你好运。 🙂

这是递归方法的尝试。 这类似于数组展平或查找匹配的括号,但复杂的是我们最多可以将三个元素跨删除的部分连接在一起。

非常轻松测试的 JavaScript 代码(欢迎使用反例/错误):

 // Returns [count, leftmostIndex] function f(A, i=0, same=1){ // Base case, end of list if (i > A.length - 1) return [0, A.length]; // We can remove this block if (A[i] == A[i+1] && same == 2){ let [count, j] = f(A, i + 2, 1); return [count + 1, j]; } // Same but the count is less than // three, keep accumulating if (A[i] == A[i+1]) return f(A, i + 1, same + 1); // Next element is different, // see if the next section has // collapsed blocks let [count, j] = f(A, i + 1, 1); // There is no available element // to try and accumulate if (j > A.length - 1) return [count, i]; // The next available element // is the same if (A[i] == A[j]){ // We've reached a count of three, // remove this block if (same == 2){ return [count + 1, j + 1]; // Haven't reached a count of // three, try one more section } else { let [count2, j2] = f(A, j + 1, 1); if (A[i] == A[j2]) return [1 + count + count2, j2 + 1]; else return [count + count2, i]; } // The next available element is // different } else { return [count, i]; } } var As = [ [4,4,7,7,6,6,6,7,4], [5,7,7,7,8,4,4,5,5,6,6,6,6,6,6,5,4] ]; for (let A of As){ console.log(JSON.stringify(A)); console.log(JSON.stringify(A.map((_, i) => i))); console.log(JSON.stringify(f(A))); }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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