【问题标题】:Remove Duplicates from Sorted Array with HashSet使用 HashSet 从排序数组中删除重复项
【发布时间】:2018-05-14 15:44:38
【问题描述】:

我对此有疑问:

对象显示给定一个排序数组,删除重复的地方,使每个元素只出现一次并返回新的长度。 不要为另一个数组分配额外的空间,您必须使用常量内存来执行此操作。例如, 给定输入数组 nums = [1,1,2], 您的函数应返回长度 = 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]

【问题讨论】:

  • 你没有做到到位。从任务描述和方法签名中,我假设检查类似于“获取nums 的第一个 元素并将它们与预期结果进行比较”。
  • Do not allocate extra space for another array。你的算法不是in place。您正在分配 new HashSet&lt;&gt;(); 更多内存。
  • 再次阅读描述:"[...] nums 的前两个元素分别为 1 和 2。" - 提示:您没有修改 nums在任何地方,前两个元素如何变成“1”和“2”?

标签: java hashset


【解决方案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

覆盖数字。

因为我不想破坏对编码的任何满足感,请继续...

策略:在纸上解决问题。

【讨论】:

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

    【讨论】:

      【解决方案3】:

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

      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)来仅跟踪唯一元素,并通过覆盖非唯一元素将它们移到前面。

      【讨论】:

        【解决方案4】:

        另一个“就地”解决方案。 只要不要求在任何地方保留重复值,并且在 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;
        
        }
        

        【讨论】:

          【解决方案5】:
          • 首先,请注意不能将 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);
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-10-01
            • 2021-11-12
            • 2021-01-27
            • 2016-01-24
            • 2022-01-03
            • 2021-12-12
            • 1970-01-01
            • 2013-11-05
            相关资源
            最近更新 更多