在O(1)时间内

时间:2017-02-17 01:42:20

标签: java arrays algorithm

给定一个大小为k的数组,前n个元素分配了一个非空引用,我将如何返回一个只包含Java中前n个n大小元素的数组?

显然你可以通过创建一个新的k大小的数组然后迭代初始n次,在每次迭代时传输元素然后那将是O(n)操作来做深度复制。

根据我对数组如何存储在内存中的理解,我认为可能只是简单地将数组的长度属性从k更改为n,然后返回初始数组的引用。

作为伪方法:

public Foo[] head(Foo[] arr, int n) {
    arr.length = n;
    return arr;
}

我想知道是否可以采取任何措施将其作为一个恒定时间操作来生成,但我担心这可能是不可能的,因为Java不支持像指针算术这样的任何东西。

如果这是不可能的,那么提供相同结果的最快方法是什么?

2 个答案:

答案 0 :(得分:3)

如果您必须使用原始数组而不是ArrayList,那么Arrays就可以满足您的需求。如果查看源代码,这些是获取数组副本的绝对最佳方法。它们确实有很多防御性编程,因为System.arraycopy()方法会在输入不合逻辑的参数时抛出大量未经检查的异常。

您可以使用Arrays.copyOf(),它将从第一个Nth元素复制到新的较短数组。

public static <T> T[] copyOf(T[] original, int newLength)
  

使用空值复制指定的数组,截断或填充(如果   必要的)所以副本有指定的长度。对于所有指数   在原始数组和副本中都有效,两个数组都会有效   包含相同的值。对于副本中有效的任何索引   但不是原始版本,副本将包含null。这些指数会   当且仅当指定的长度大于。的长度时才存在   原始数组。结果数组与类完全相同   原始阵列。

2770
2771    public static <T,U> T[] More ...copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
2772        T[] copy = ((Object)newType == (Object)Object[].class)
2773            ? (T[]) new Object[newLength]
2774            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
2775        System.arraycopy(original, 0, copy, 0,
2776                         Math.min(original.length, newLength));
2777        return copy;
2778    }

Arrays.copyOfRange()也可以解决问题:

public static <T> T[] copyOfRange(T[] original, int from, int to)
  

将指定数组的指定范围复制到新数组中。   范围(from)的初始索引必须介于0和0之间   original.length,包括。原始[from]的值被放入   副本的初始元素(除非来自== original.length或   从==到)。原始数组中后续元素的值为   放入副本中的后续元素。最终的指数   范围(to),必须大于或等于,可以是   大于original.length,在这种情况下null放在所有   索引大于或等于的副本的元素   original.length - 来自。返回数组的长度为 -   从。生成的数组与原始数组完全相同   阵列。

3035    public static <T,U> T[] More ...copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {
3036        int newLength = to - from;
3037        if (newLength < 0)
3038            throw new IllegalArgumentException(from + " > " + to);
3039        T[] copy = ((Object)newType == (Object)Object[].class)
3040            ? (T[]) new Object[newLength]
3041            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
3042        System.arraycopy(original, from, copy, 0,
3043                         Math.min(original.length - from, newLength));
3044        return copy;
3045    }

正如您所看到的,这两个都只是System.arraycopy上的包装函数,具有防御逻辑,您尝试执行的操作是有效的。

System.arraycopy是复制数组的绝对最快的方式。

答案 1 :(得分:2)

您正在寻找sublist。 (列表而不是数组)

但是,重点始终如一。保存n和数组的值。你已经完成了。你可以使用那些相同的东西,你使用假装不同大小的不同假阵列,只是假装数组大小为n,并使用数组。

虽然你必须,

List<MyClass> subArray = Arrays.asList(array).subList(index, index2);