从数组中删除秘密元素的最有效方法? Java

问题描述 投票:2回答:3

我正在尝试以最有效的方式解决此问题。

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

例如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。

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

    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循环。

到目前为止,我还无法弄清楚如何终止代码,因此出现了无限循环。我是编程新手,不胜感激。

java arrays algorithm loops for-loop
3个回答
2
投票

我被告知我的代码需要太多操作且速度太慢。

是正确的,因为您实际上可以执行此操作而无需修改数组。

由于这是您要完成的任务,所以我将向您展示如何做到这一点,而无需编写任何代码。

  1. 将计数器初始化为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
            │   │                    O R         │   │
    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
        │         │       O R       │         │
    4,4,7,7,6,6,6,7,4             4,7,6,6,6,7,7,4,4
    
      start                       start
        │        end                │        end
        │         │       O R       │         │
    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,以搜索下一个三元组。

如您所见,数组从未修改,我们只是将索引值用于数组中。与简单地修改数组然后再试相比,这需要more code,但是新代码的运行速度更快,因为我们不必在周围复制数组元素。

祝您好运。 🙂


2
投票

您的逻辑中有几处错误。而不是指出它们中的每一个,这是一种新方法:

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。


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.