简体   繁体   English

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

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

I am trying to solve this problem in the most efficient way.我试图以最有效的方式解决这个问题。

Given an array of integers, keep removing three consecutive same integers until there are no more three consecutive same elements in an array and return number of times those elements appeared.给定一个整数数组,继续删除三个连续的相同整数,直到数组中不再有三个连续的相同元素,并返回这些元素出现的次数。

For example int[] {4,4,7,7,6,6,6,7,4} will return 3. When we remove consecutive 6's int array becomes {4,4,7,7,7,4} in the next iteration, consecutive 7's are removed and we're left with {4,4,4} and so on.例如 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} would return 0. int[] {3,4,4,5,5,3} 将返回 0。

I've been trying a dozen of times using different collections but i have been said that my code requires to many operations and is too slow.我已经尝试了十几次使用不同的集合,但有人说我的代码需要很多操作,而且速度太慢。 So i wanted to use arrays only but i got stuck.所以我只想使用数组,但我被卡住了。 Here is my code:这是我的代码:

    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;
}

The algorithm iterates over an array and adds the items to the second array, if there are consecutive elements, it adds to a counter and skips over them.该算法迭代一个数组并将项目添加到第二个数组,如果有连续元素,则添加到计数器并跳过它们。 On the last iteration, the arr is set to arr2 and for loop should reset.在最后一次迭代中,arr 设置为 arr2 并且 for 循环应该重置。

So far am i unable to figure out how to terminate the code so i got an infinite loop.到目前为止,我无法弄清楚如何终止代码,所以我得到了一个无限循环。 I am new to programming and would appreciate any help.我是编程新手,希望得到任何帮助。

There are several things wrong in your logic.你的逻辑有几处错误。 Instead of pointing each of them out, here is a new approach:这里没有指出每个人,而是一种新方法:

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;
}

Here, we add elements to a new array one by one and maintain an index for that array.在这里,我们将元素一个一个地添加到一个新数组中,并为该数组维护一个索引。 When there are 3 elements in the new array, compare the last 3. If they are equal, decrement the index ('j') by 3.当新数组中有 3 个元素时,比较最后 3 个。如果它们相等,则将索引 ('j') 减 3。

I have been told that my code requires too many operations and is too slow.有人告诉我,我的代码需要太多操作,而且速度太慢。

That is correct, because you can actually do this without ever modifying the array.这是正确的,因为您实际上可以在不修改数组的情况下执行此操作。

Since this is an assignment for you to complete, I'm just going to show you how to do that, without writing any code.由于这是一项需要您完成的作业,因此我将向您展示如何做到这一点,而无需编写任何代码。

  1. Initialize counter to 0, and start iterating from the beginning of the array.将 counter 初始化为 0,并从数组的开头开始迭代。

  2. Locate the next (first) triplet.找到下一个(第一个)三元组。
    If not found, you're done, so return the counter value.如果没有找到,你就完成了,所以返回计数器值。

     start │ end │ │ 4,4,7,7,6,6,6,7,4
  3. You found a triplet to remove, so increment the counter by 1.您找到了要删除的三元组,因此将计数器加 1。

  4. Compare the surrounding values.比较周围的值。 First compare the values right before and after.首先比较前后的值。
    If different, skip to step 7.如果不同,请跳到第 7 步。

     start │ end │ │ 4,4,7,7,6,6,6,7,4 └───────┘ are they equal?
  5. When surrounding values are equal, there are two possibilities for a cascade triplet, either an extra value before, or an extra value after.当周围的值相等时,级联三元组有两种可能性,一个是之前的额外值,一个是之后的额外值。
    If the extra value before/after are both different from surrounding values, skip to step 7.如果之前/之后的额外值都与周围值不同,请跳到步骤 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. Expand the sequence to remove, and go back to step 3 to repeat the cascade search.展开要移除的序列,然后返回步骤 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. Now we need to look for a more complicated disjoint triplet.现在我们需要寻找一个更复杂的不相交三元组。

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

    To do that, we need to keep track of a previous sequence removed.为此,我们需要跟踪删除的先前序列。

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

    If the previous end is 2 positions before the new start, and the 3 values before, between, and after are the equal, then we found a disjoint triplet.如果前一个结束在新开始之前的 2 个位置,并且之前、之间和之后的 3 个值相等,那么我们找到了一个不相交的三元组。 Expand the sequence-to-remove to include both previous sequence, current sequence, and new triplet, then go back to step 3 to repeat the cascade search.展开要删除的序列以包括先前的序列、当前的序列和新的三元组,然后返回步骤 3 以重复级联搜索。

  8. You have now found a section to remove, and incremented the counter the appropriate number of times, so starting after the end position, go back to step 2 to search for the next triplet.您现在已找到要删除的部分,并将计数器增加适当的次数,因此从end位置开始,返回步骤 2 以搜索下一个三元组。

As you can see, the arrays are never modified, we're just working with index values into the array.如您所见,数组永远不会被修改,我们只是将索引值处理到数组中。 This requires more code than simply modifying the array and trying again, but the new code runs much faster, because we don't have to copy array elements around.这需要更多的代码,而不是简单地修改数组并重试,但新代码运行得更快,因为我们不必复制数组元素。

Good luck code that.祝你好运。 🙂 🙂

Here's an attempt at a recursive approach.这是递归方法的尝试。 This is similar to array flattening or finding matching parentheticals, with the complication that we can have up to three elements to tie together across removed sections.这类似于数组展平或查找匹配的括号,但复杂的是我们最多可以将三个元素跨删除的部分连接在一起。

Very lightly tested JavaScript code (counterexamples/bugs welcome):非常轻松测试的 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