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以重复级联搜索。
您现在找到了要删除的部分,并将计数器增加了适当的次数,因此从
如您所见,数组永远不会被修改,我们只是将索引值用于数组中。与简单地修改数组并重试相比,这需要更多的代码,但是新代码的运行速度更快,因为我们不必在周围复制数组元素。
祝您好运。 ??
这里是递归方法的尝试。这类似于数组展平或找到匹配的括号,这很复杂,因为我们最多可以有三个元素将删除的部分连接在一起。
非常经过测试的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))); } |