2017-02-17 37 views
-2

給定一個大小爲k的數組,前n個元素指定了非空引用,如何返回僅包含前n個數組的數組Java中大小爲n的元素?在O(1)時間返回ak大小數組的前n個元素時間

很明顯,你可以通過創建一個新的k大小的數組來做一個深層複製,然後迭代n次,在每次迭代中傳遞元素,但這會是一個O(n)操作。

我認爲可能從我理解數組如何存儲在內存中將簡單地將數組的長度屬性從k更改爲n,然後返回初始數組的引用。

作爲一個僞方法:

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

我想知道,什麼都可以做生產這是一個固定時間的操作,但我擔心它可能是不可能的,因爲Java不支持像指針運算東西。

如果這是不可能的,那麼提供相同結果的最快捷方式是什麼?

+1

你不能在O(1)時間內做到這一點。 Java中數組的長度不能改變,所以你需要創建一個新的。 Jarrod的答案提供瞭如何正確執行此操作的詳細信息。 –

+0

@Math謝謝,只是想知道它是否可行更快。 –

回答

2

如果必須使用原始陣列的工作,而不是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)必須位於零和 original.length之間,包括在內。原始[來自]的值被放入副本的初始元素 (除非== === original.length或從== ==到 )。原始數組中隨後元素的值是 ,放置在副本中的後續元素中。 範圍(to)的最終索引必須大於或等於from,可能是 大於original.length,在這種情況下null將放置在索引大於或等於該索引的副本的所有 元素中到 original.length - from。返回數組的長度將從 - 。得到的數組與原始的 數組完全相同。

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是複製數組的絕對最快的方法。

+0

謝謝。兩個實用函數都使用System.arraycopy,它與新數組大小成線性關係。在這種情況下,時間不變是不可能的? –

+1

這是正確的答案。時間不變是不可能的。這是一樣好。 –

+0

你可以得到你想要的東西的唯一方法是使用類似Guava中的'Iterators.filter(iterable,Predicate)'函數。他們很懶,只處理他們被訪問的項目。但它們不是原始數組,這是有效(時間和空間)獲取子數組並保持原始數組的唯一方法。 –

2

您正在查找sublist。 (列表而不是數組)

但是,點總是相同的。保存n和數組的值。你已經完成了。你可以用同樣的東西來使用假裝不同大小的僞數組,假裝數組的大小爲n,然後使用數組。

但如果你一定要,

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

謝謝。我知道List.subList(),但不幸的是,我被限制在方法結束時返回一個數組。 :/ –

+0

然後沒有一個。只需使用Array.CopyOf(n),這是唯一合理的解決方案。內部複製例程非常快。就目前情況而言,這是使用System.arrayCopy()移動數據的最快方式,這是Copyof在內部使用的。 – Tatarize

相關問題