簡體   English   中英

使用HashSet從排序數組中刪除重復項

[英]Remove Duplicates from Sorted Array with HashSet

我對此有疑問:

該對象顯示給定一個已排序的數組,將重復項刪除就位,以便每個元素僅出現一次並返回新的長度。 不要為另一個數組分配額外的空間,必須使用恆定的內存就位。例如,給定輸入數組nums = [1,1,2],您的函數應返回length = 2,其中nums的前兩個元素分別是1和2。 超出新長度后剩下的都無所謂。

我使用HashSet來執行此問題,但結果始終顯示為[1,1]。 我想不通,有人可以幫我知道問題出在哪里嗎?

我的代碼:

class Solution {
    public int removeDuplicates(int[] nums) {
        if (nums.length == 0) return 0;
        Set<Integer> numset = new HashSet<>();
        for(int i:nums){
            numset.add(i);
        }
        return numset.size();
    }
}

您的輸入[1,1,2]您的答案[1,1]預期的答案[1,2]

假設您有一個排序數組:

int[] nums = { 1, 2, 2, 2, 4, 5, 5, 5, 7, 7, 8 };

... walk through nums, at some read position check for being a duplicate,
... (otherwise) write it compact at the write position
... return new length

覆蓋數字。

由於我不想破壞任何編碼的滿意度,因此請繼續...

策略:在紙上解決問題。

  • 您的解決方案不是就地解決方案
  • 由於使用的是哈希集,因此您違反了恆定內存規則。
  • 在Java中,初始化后就無法縮小數組大小。

因此,這里是針對您的問題的簡單就地解決方案,其最壞情況下的時間復雜度為O(n)。

public int removeDuplicates(int[] nums){

    int length = nums.length;
    int index = 0;

    for(int i = 0; i < length - 1; i++){
        if(nums[i] == nums[i+1]){
            nums[index++] = nums[i];
        }
    }
    // this is needed because upper for loop runs until i equals to length-2
    // in order to avoid ArrayOutOfBoundException 
    nums[index++] = nums[length-1];

    // for displaying the unique array
    /*
    for(int i = 0; i < index; i++){
        System.out.println(nums[i]);
    }
    */

    return index;
}

使用額外的數據結構也違反了您提到的規則,即不要為其分配額外的空間。 現在,由於您的數組已經排序,因此以下代碼可以正常工作。

int solution(int[] nums) {
    int size = nums.length;
    if (size == 0 || size == 1) {
        return size;
    }
    int next = 0;

    for (int i = 0; i < size - 1; i++) {
        if (nums[i] != nums[i + 1]) {
            nums[next++] = nums[i];
        }
    }
    nums[next++] = nums[size - 1];

    return next;
}

在上面的代碼中,我們只是維護一個額外的索引(next)以僅跟蹤唯一元素,並通過覆蓋非唯一元素將它們移到最前面。

  • 首先,請注意, 在分配給之后 ,您不能使用一種方法縮小Java的經典數組。 由於Java是傳遞值
  • 如果仍然堅持就地刪除重復項,則需要放置一個分隔符,例如Integer.MAX_VALUEInteger.MIN_VALUE 然后,直到達到該值,然后遍歷它的大小,或者在需要的地方進行操作。
  • 但是,就地刪除似乎不足以實現此目的,因此我建議返回新數組。

怪異的解決方案,

private static int removeDuplicatesWithDelimiter(int[] nums) {
    if (nums.length == 0) return 0;


    Set<Integer> numset = new HashSet<>();
    for(int i : nums){
        numset.add(i);
    }

    int newArraySize = numset.size();

    for (int i = 0; i < newArraySize; ++i) {
        nums[i] = (Integer) numset.toArray()[i];
    }

    nums[newArraySize] = Integer.MIN_VALUE;

    return newArraySize;
}

更好的解決方案

class ArrayDuplicateTest {

    private static int[] removeDuplicates(int[] list) {
        int newLength = list.length;
        // find length w/o duplicates:
        for (int i = 1; i < list.length; i++) {
            for (int j = 0; j < i; j++) {
                if (list[i] == list[j]) {   // if duplicate founded then decrease length by 1
                    newLength--;
                    break;
                }
            }
        }

        int[] newArray = new int[newLength]; // create new array with new length
        newArray[0] = list[0];  // 1st element goes to new array
        int inx = 1;            // index for 2nd element of new array
        boolean isDuplicate;

        for (int i = 1; i < list.length; i++) {
            isDuplicate = false;
            for (int j = 0; j < i; j++) {
                if (list[i] == list[j]) {  // if duplicate founded then change boolean variable and break
                    isDuplicate = true;
                    break;
                }
            }
            if (!isDuplicate) {     // if it's not duplicate then put it to new array
                newArray[inx] = list[i];
                inx++;
            }
        }
        return newArray;
    }

    public static void main(String[] args) {
        int nums[] = {1, 1, 2, 3, 5, 6,6 ,6};

        int noDup[] = removeDuplicates(nums);

        for (int i : noDup) {
            System.out.println(i + "    ");
        }

        System.out.println("length: " + noDup.length);
    }
}

另一個“就地”解決方案。 只要沒有要求在任何地方保留重復值,並且Java中沒有辦法在沒有新數組的情況下縮小數組,則將重復項替換為MAX_VALUE,然后排序到數組末尾。 (請參見代碼中的注釋)

順便說一句:在方法執行期間聲明了一個變量uniqueCount

public int removeDuplicates(int[] nums) {

 if (nums.length == 0) return 0;

// at least one element is unique
int uniqueCount = 1;

for (int i = 0; i < nums.length - 1; i++) {
    if (nums[i] == nums[i + 1]) {
    // duplicate value replaced with Integer.MAX_VALUE to be at the end of array 
    nums[i] = Integer.MAX_VALUE;
    } else {
    // nums[i] is unique
    uniqueCount++;
    }
}
// Re-sort array to move MAX_VALUE elements to the end of array
Arrays.sort(nums);
return uniqueCount;

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM