在Java中,我们有一个数组int[] a = new int[10000000];
完全用任意数字填充。我们需要在代码中删除任意子序列:这是一组可能不连续的元素。
使用int[]
超过LinkedList
的原因是在传递元素时获得了速度提升。目前没有元素的删除,因此在运行应用程序时存储了大量垃圾。删除元素可能会加快速度,这是一个非常有趣的问题。
如何以最快的方式从数组中删除子序列?
答案 0 :(得分:2)
这取决于您是要缩短数组还是允许在数组末尾使用未使用的元素。这个工具是System.arraycopy
。要缩短数组,您需要分配一个新数组:
public int[] remove(int[] original, removeStart, removeEnd) {
int originalLen = original.length;
int[] a = new int[originalLen - removeEnd - removeStart];
System.arraycopy(original, 0, // from original[0]
a, 0, // to a[0]
removeStart); // this many elements
System.arraycopy(original, removeEnd, // from original[removeEnd]
a, removeStart, // to a[removeStart]
originalLen - removeEnd); // this many elements
return a;
}
要压缩数组:
System.arraycopy(array, removeEnd, // from array[removeEnd]
array, removeStart, // to array[removeStart]
array.length - removeEnd); // this number of elements
您不必担心重叠范围; arraycopy
正确处理了这些内容。
如果你要删除不连续的元素范围,你可以推广其中一个解决方案(更少移动的东西,但更复杂的代码)或者你可以单独删除每个连续块(更容易编程,但你会移动围绕您将要丢弃的数据。)
如果您要删除分散的索引,我会手动完成。设计取决于它是分散的个别指数还是它是一系列范围。对于后者(这是未经测试的,但它应该给你的想法):
/**
* Simple class to hold the start and end of a range.
*/
public static class Range implements Comparable<Range> {
int start;
int end;
public int compareTo(Range other) {
if (start < other.start) return -1;
if (start > other.start) return 1;
if (end < other.end) return -1;
if (end > other.end) return 1;
return 0;
}
}
/**
* Remove a list of ranges from an array.
* @param original the array from which to remove the values.
* @param toRemove the list of ranges to remove. This must be
* sorted in ascending order of range start before calling this method.
* @param compact flag indicating whether to simply compact the original
* array or to copy the values into a new array. If false, will allocate
* a new array of the exact size needed to contain the elements not removed.
*/
public int[] remove(int[] original, List<Range> toRemove, boolean compact) {
int[] a;
if (compact) {
a = original;
} else {
int len = 0;
for (Range range : toRemove) len += range.end - range.start;
a = new int[original.length - len];
}
int nextSource = 0;
int nextDest = 0;
for (Range range : toRemove) {
if (nextSource < range.start) {
System.arraycopy(original, nextSource, a, nextDest,
range.start - nextSource);
nextDest += range.start - nextSource;
nextSource = range.start;
}
nextSource = range.end;
}
if (nextSource < original.length) {
System.arraycopy(original, nextSource, a, nextDest,
original.length - nextSource);
}
return a;
}
答案 1 :(得分:0)
使用[ System#arraycopy ](http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/System.html#arraycopy(java.lang .Object,int,java.lang.Object,int,int))如下:
System.arraycopy(orginalArray, startIndex, newArray,
newArrayStartIndex, numOfElementsToCopy);
orginalArray = newArray;
请注意:这适用于连续的位置。如果有更多的连续部分,仍然有用,并且可以以类似的方式多次调用。 但是如果要删除的位置是完全随机的,那么我相信你需要遍历数组。