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

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。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    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循环。

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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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。


I have been told that my code requires too many operations and is too slow.

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

由于这是您要完成的任务,因此我将向您展示如何完成此任务,而无需编写任何代码。

  • 将计数器初始化为0,然后从数组的开头开始迭代。

  • 找到下一个(第一个)三元组。
    如果未找到,您已经完成,因此返回计数器值。

    1
    2
    3
    4
          start
            │  end
            │   │
    4,4,7,7,6,6,6,7,4
  • 您发现要删除的三元组,因此将计数器增加1。

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

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

    1
    2
    3
    4
    5
          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?
  • 展开要删除的序列,然后返回到步骤3以重复级联搜索。

    1
    2
    3
    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
    1
    2
    3
    4
    5
      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?

  • 现在,我们需要寻找更复杂的不相交的三元组。

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

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

    1
    2
    3
    4
    5
    6
      ┌ prevStart
      │    ┌ prevEnd
      │    │ ┌ start
      │    │ │    ┌ end
    12344433255666527
     └──────┴──────┘   are they equal?

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

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

  • 如您所见,数组永远不会被修改,我们只是将索引值用于数组中。与简单地修改数组并重试相比,这需要更多的代码,但是新代码的运行速度更快,因为我们不必在周围复制数组元素。

    祝您好运。 ??


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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    // 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)));
    }