使用HashSet从Sorted Array中删除重复项

时间:2018-05-14 15:44:39

标签: java 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]

5 个答案:

答案 0 :(得分:1)

假设你有一个排序数组:

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

覆盖nums。

由于我不想破坏编码方面的任何满足感,请继续......

战术:在纸上解决问题。

答案 1 :(得分:1)

  • 您的解决方案不是就地解决方案
  • 由于您使用的是哈希集,因此违反了常量内存规则。
  • 在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;
}

答案 2 :(得分:0)

使用额外的数据结构也违反了您提到的规则,即不为其分配额外的空间。 现在,由于您的数组已经排序,以下代码将正常工作。

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;
}

在上面的代码中,我们只是维护一个额外的索引(下一个)来跟踪唯一元素,并通过覆盖非唯一元素将它们移到前面。

答案 3 :(得分:0)

  • 首先,要注意你不能缩小Java中的Java经典数组 方法 after allocated to。由于Java是pass-by-value
  • 如果您仍然坚持原地删除重复项,则需要放置 像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);
    }
}

答案 4 :(得分:0)

另一个&#34;就地&#34;解。 只要没有要求在任何地方保留重复值,并且Java没有办法在没有新数组的情况下缩小数组,重复项将替换为MAX_VALUE,然后排序到数组的末尾。 (请参阅代码中的内容)

BTW:在方法执行期间声明了一个变量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;

}