2015-06-23 23 views
0

我需要一個java代碼,它可以從數組中刪除重複項而不改變元素的順序,並且不使用集合或排序技術。刪除數組中的副本而不會影響元素的順序而不使用集合

例如: 如果輸入數組是{23,1,5,4,2,23,6,2,4} 然後輸出應爲{23,1,5,4,2,6}

+0

這是不是要求您的問題的代碼的地方。 –

+0

[this element](http://stackoverflow.com/a/7055544/572670)詳細闡述了[element distinctness](https://en.wikipedia.org/wiki/Element_distinctness_problem)的難點。您始終可以使用符合您要求的雙迴路的天真O(n^2)解決方案。 – amit

+0

你是說沒有套,因爲你想保留的順序,或者因爲你有一些任意的原因(家庭作業,測驗問題),只是不使用任何集? – Paul

回答

3

你可以用Ø做到在O(n^2)時間( 1)額外空間

public static int[] noSpaceElementDistinctness(int[] arr) { 
    int n = arr.length; 
    for (int i = 0; i < n;i++) { 
     boolean exists = false; 
     for (int j = 0; j < i; j++) { 
      if (arr[i] == arr[j]) { 
       exists = true; 
       break; 
      } 
     } 
     if (exists) { 
      for (int j = i+1; j<n; j++) 
       arr[j-1] = arr[j]; 
     n--; 
     i--; //to iterate the next element, which is now at index i, not i+1. 
     } 
    } 
    for (int i = n; i < arr.length; i++) arr[i] = Integer.MIN_VALUE; //indicates no value 
    return arr; 

} 

作爲一個側面說明,元素清晰度問題不是小事有效地解決,因爲它可能從第一眼看上去,這是一個問題,嚴格的下界,你可以做些什麼來解決它有效。 This thread討論它。

0

創建一個新的ArrayList()。在舊列表中循環並將值複製到新的值,除非它已經在其中。

順序將會改變,因爲你不會複製所有...

+0

因此,基本上 - 使用O(n),額外的空間,但以低效的方式來做。 – amit

+0

O(x)與大型數組相關。該信息不在問題中。 – Danielson

+0

沒有理由使用額外的'ArrayList',你可以使用一個集合在O(n)時間+空間中完成它,或者你可以在O(n^2)時間內完成它,而不需要額外的名單。 – amit

1

如果使用Java 8簡單的方法是:

int[] array = {23, 1, 5, 4, 2, 23, 6, 2, 4}; 
int[] noDupes = IntStream.of(array).distinct().toArray(); 
System.out.println(Arrays.toString(noDupes)); // [23, 1, 5, 4, 2, 6] 
+0

這使用O(n)額外的空間,關於java8流的AFAIK – amit

+0

@amit而且操作效率不高,因爲它首先將原語裝箱,但它顯然無所謂這個大小的數組。如果該操作在大型陣列上工作,那麼肯定會有更有效的方法。 – assylias

0

有幾個選擇 - 一些比其他人更有效:

/** 
* Brute force approach - very inefficient. 
* 
* Finds each duplicate and removes it. 
*/ 
private int[] removeDupesUsingNoExtraMemory(int[] a) { 
    int length = a.length; 
    for (int i = 0; i < length - 1; i++) { 
     for (int j = i + 1; j < length; j++) { 
      if (a[i] == a[j]) { 
       // No point copying if this is the last one. 
       if (j < length - 1) { 
        // Remove a[j]. 
        System.arraycopy(a, j + 1, a, j, length - j - 1); 
       } 
       length -= 1; 
      } 
     } 
    } 
    // Actually it does use extra memory but only to trim the array because Java cannot slice arrays. 
    return Arrays.copyOf(a, length); 
} 

/** 
* A bit more efficient. 
* 
* Copies only non-duplicate ones. 
*/ 
private int[] removeDupesDifferently(int[] a) { 
    int length = a.length; 
    // Copying to the end backwards. 
    int to = length - 1; 
    // Copy backwards so we remove the second duplicate - not the first. 
    for (int i = length - 1; i >= 0; i--) { 
     boolean duplicate = false; 
     for (int j = 0; j < i && !duplicate; j++) { 
      duplicate |= a[i] == a[j]; 
     } 
     if (!duplicate) { 
      a[to--] = a[i]; 
     } 
    } 
    return Arrays.copyOfRange(a, to + 1, a.length); 
} 

/** 
* Most efficient - but uses a `Set`. 
* 
* Builds a `Set` of `seen` values so we don't copy duplicates. 
*/ 
private int[] removeDupesUsingASet(int[] a) { 
    int to = 0; 
    Set<Integer> seen = new HashSet<>(); 
    for (int i = 0; i < a.length - 1; i++) { 
     // Seen it before? 
     if (!seen.contains(a[i])) { 
      a[to++] = a[i]; 
      // Seen that one - don't want to see it again. 
      seen.add(a[i]); 
     } 
    } 
    return Arrays.copyOf(a, to); 
} 

public void test() { 
    System.out.println("removeDupesUsingNoExtraMemory = " + Arrays.toString(removeDupesUsingNoExtraMemory(new int[]{23, 1, 5, 4, 2, 23, 6, 2, 4}))); 
    System.out.println("removeDupesDifferently = " + Arrays.toString(removeDupesDifferently(new int[]{23, 1, 5, 4, 2, 23, 6, 2, 4}))); 
    System.out.println("removeDupesUsingASet = " + Arrays.toString(removeDupesUsingASet(new int[]{23, 1, 5, 4, 2, 23, 6, 2, 4}))); 
} 
0
int arr[] = {23,1,5,4,2,6} ; 
    List<Integer> list = new ArrayList<Integer>(); 
    for(int i = 0; i<arr.length; i++) { 
     if (!list.contains(arr[i])) { 
      list.add(arr[i]); 
     } 
    } 

    Iterator it = list.iterator(); 
    while(it.hasNext()){ 
     System.out.println(it.next()); 
    } 
0

如果您只需要在不修改陣列的情況下打印唯一元素,則可以使用此替代解決方案來完成。排序爲O陣列(N log n)的(合併排序例如),並通過在陣列O(n)的運行只打印有它們的相鄰元件不同的元件,即:

if(arr[i] != arr[i + 1]) { 
    print(arr[i]); 
} 

乾杯!

+0

查看問題中的示例:您的建議是否打印九個值,六個或中間的某個位置?它是否符合要求的輸出要求? – greybeard

+0

啊,沒注意。這隻有在沒有訂單重要時纔有效 – stefo0O0o

相關問題