【问题标题】:Removing duplicates from an array (without sets or sorting)从数组中删除重复项(没有集合或排序)
【发布时间】:2014-10-25 22:57:33
【问题描述】:

我有以下代码:

import java.util.Scanner;
public class ArrayDuplicates {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        System.out.print("How many numbers are you going to enter? ");
        int num = scan.nextInt();
        int[] arr = new int[num]; // initialize array with user inputted length
        for (int i = 0; i < arr.length; i++) { // enter numbers into array
            arr[i] = scan.nextInt();
        }

        int[] unique = new int[arr.length];    //initialize new array that will hold unique values
        for (int i = 0; i < arr.length; i++) {
            boolean b = true;    //boolean that checks if an element is a duplicate
            for (int j = i+1; j < arr.length; j++) {    //check all elements above int i
                if (arr[i] == arr[j]) {
                    b = false;    // set b to false if there is an existing duplicate
                }
            }
            if (b) {
                unique[i] = arr[i];    // if no duplicates exist, then it is unique.
            }
        }   
        for (int i = 0; i < unique.length; i++) {
                System.out.println(unique[i]);
        }
    }
}

这段代码的问题(除了对于大型数组来说非常慢,但这不是重点)是因为 unique 数组的未声明元素将被设置为 0,第一个中的重复元素数组在unique[] 中被设置为0(如果有任何意义的话)。我理解为什么会发生这种情况,但找不到解决此问题的有效方法。我尝试在唯一数组中将重复元素设置为Integer.MIN_VALUE,然后只打印不等于Integer.MIN_VALUEunique[] 的元素,但这似乎是解决问题的一个弱解决方案。我该如何解决这个问题?

编辑:如果我运行代码:

你要输入多少个数字? 4
1
2
2
0

输出:

1
0
2
0

由于数组的第二个元素是重复的,我没有将unique[1] 设置为任何值,使其默认为 0。如何避免打印该 0,因为它不是原始数组的一部分?

编辑 2: 是的,这是作业,但我不想使用集合、排序等的原因主要是我不熟悉它们。另外,由于我没有要求任何人为我编写整个程序,所以我认为寻求一点帮助是可以的。

【问题讨论】:

  • 恐怕这对我来说没有任何意义,也许您可​​以改写您在问题中想说的内容?
  • 您是否考虑过一开始就不向数组添加重复项?
  • 您可以在创建unique 数组之前计算arr 中的唯一元素
  • 不使用 List 或 Set 解决方案会变得非常混乱。如果您不必使用列表或集合,我只是建议将重复值设置为 Integer.MIN_VALUE,就像您说的那样,或者创建一个布尔值的并行
  • Java 数组不是动态调整大小的,因此您无法在没有更多代码的情况下删除元素。此外,MapList 不是 Set 或排序。

标签: java arrays duplicates duplicate-removal


【解决方案1】:

您选择的任何值(零、最小整数、最大整数)来表示已删除的重复项都是一个问题。用户总是可以输入该数字,而您的程序将无法正常运行。 (您可以合法使用(例如)min-int 或 max-int 的唯一方法是,如果要求明确说明该数字是无效输入。)

处理重复的正确方法是保留非重复数量的计数器,并确保重复(或包含它们的插槽)位于数组的高端;即索引> =计数器。 (这成为您的算法需要维护的不变量......)

最好的解决方案是在将重复项添加到数组之前消除它们。记录非重复项的数量并进行迭代,直到达到您的 num ... 而不是数组的长度。

但是,如果您确实想将所有值添加到数组中并然后消除重复项,那么当您发现重复项时,您需要交换元素以便保持不变量。逻辑有点繁琐......但非常可行。

更新

我刚刚注意到您最初的解决方案是使用两个数组。我假设您使用的是一个数组,并进行就地更新以消除重复项。

【讨论】:

  • 这是真的,我承认这是我的回答中的一个缺陷,但 OP 承认这是家庭作业,只想要一个使用 OP 知道如何使用和可以处理的工具的答案一组合理的输入。您的观点仍然有效,只是这是作业,答案被蒙蔽了
  • “为任何人提供高质量答案的想法。” - 对功能要求(如上所述)的高质量答案是根本不使用数组. (使用数组不是功能要求。它是一个实现约束......对于任何试图为 Java SE、EE、Android 编写高质量代码的人来说没有多大意义。)跨度>
  • 所以我的理解是我应该检查每个输入的整数与以前的输入,如果它是唯一的,则只将它添加到原始数组中。还有一个计数器,用于计算已添加到数组中的输入数量(即唯一的输入)。然后创建一个长度为counter 的新数组,其中包含原始数组的第一个counter 元素。这是你说的吗?在这种情况下,我不需要确保重复项接近数组的末尾,对吗?
  • @Kootling - 你已经明白我在说什么了。
  • 也许我说错了。这取决于您是在之前还是之后消除重复项。在前一种情况下,你是对的。重复项根本不应该在数组中,大于“计数”位置的槽可以保持初始状态。 (只是不要打印它们......)无论如何,你应该自己考虑一下,而不是相信我(或任何其他人)的话。
【解决方案2】:

我将使用你用来解决问题的工具,因为我的某些东西告诉我这是家庭作业...

import java.util.Scanner;

public class ArrayDuplicates 
{

   public static void main(String[] args) 
   {

      Scanner scan = new Scanner(System.in);

      System.out.print("How many numbers are you going to enter? ");
      int num = scan.nextInt();

      int[] arr = new int[num]; // initialize array with user inputted length

      for (int i = 0; i < arr.length; i++)// enter numbers into array
      {

         arr[i] = scan.nextInt();

      }

      double[] unique = new double[arr.length];    //initialize new array that will hold unique values

      ///////My edit

      for(int z = 0; z < unique.length; z++)
      {

         unique[z] = -0.5;

      }

      ///////

      for (int i = 0; i < arr.length; i++) 
      {

         boolean b = true;    //boolean that checks if an element is a duplicate

         for (int j = i+1; j < arr.length; j++)    //check all elements above int i
         {

            if (arr[i] == arr[j]) 
            {

               b = false;    // set b to false if there is an existing duplicate

            }

         }

         if (b) 
         {

            unique[i] = arr[i];    // if no duplicates exist, then it is unique.

         }

      }   

      for (int i = 0; i < unique.length; i++) 
      {

         if(!(unique[i] == -0.5))
         {

            System.out.println((int)(unique[i]));

         }

      }

   }
}

那么,你看到我在哪里注释掉了我的编辑吗?这是新事物,一个非常简单的检查方法是给值一个预期的数字,在这种情况下,是一个负数。现在,这是我的一个假设,将 -1 更改为您知道将不会输入到 Scanner 的任何值。 if 语句也一样。

【讨论】:

  • 这个答案对我来说最有意义,因为这是我一开始想做的事情。不过不知道什么值不会输入,所以决定用double array,用0.5作为不会输入的值(输入的值应该是整数,所以不要输入0.5) .
【解决方案3】:

最好的方法是使用Map

public interface Map<K,V>

将键映射到值的对象。地图不能包含重复项 钥匙;每个键最多可以映射到一个值。

我不知道你为什么不想使用一套,除非你在做作业......


如果你真的不能使用一套。继续创建ArrayList。将array 的元素存储在其中,但每次要存储时,请检查该元素是否已经是ArrayList 的一部分。

 int [] list = {5, 5, 3, 2, 5, 3, 5};

 ArrayList<Integer> list2 = new ArrayList<Integer>();

 for(int i = 0; i < list.length; i++)
    if(!list2.contains(list[i]))
        list2.add(list[i]);

如果需要,您可以将 ArrayList 转回数组。

Object[] list3 = list2.toArray();

【讨论】:

  • @DreadHeadedDeveloper 我知道如何使用ArrayList,但哇Map 太干净了。
  • 这是为这类事情而生的工具
  • 是的,这是作业,但我不想使用集合、排序等的原因主要是我对它们不熟悉。另外,由于我没有要求任何人为我编写整个程序,我认为寻求一点帮助是可以的。
  • @Kootling 使用 ArrayList 来实现,就像我在上面所做的那样。
  • @Kootling 看看ArrayList 是什么:docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html 简而言之,它是一个更强大的数组。
【解决方案4】:

您可以存储用户输入的最大值(当用户在第一个循环中输入值时),然后使唯一性的默认值等于 max + 1。

或者您可以尝试另一种解决问题的方法,如下所示:

  int num = scan.nextInt();
  int[] arr = new int[num];
  int[] uniq = new int[num+1000000];
  int j = 0;

  // enter numbers into array
  for (int i = 0; i < arr.length; i++) { 
     int input = scan.nextInt(); 
     if(uniq[input] != 1){
         uniq[input] = 1;  
         arr[j] = input;
         j++;
      }
   } 

   for (int i = 0; i < j; i++) {
      System.out.println(arr[i]);
   }

请注意,此解决方案假设用户不会输入大于(num + 1,000,000) 的数字。

【讨论】:

  • 嗯,OP担心效率低下,我必须给-1以表示效率低下,因为这是OP特别要求的......
  • 但这只需要 O(num + j).. 所以实际上这更有效:)
  • 当您创建一百万个单位长的数组时,这并不意味着任何事情......当单个动作的负载超过该动作的效率时,效率可能会受到限制
  • 在性能和存储之间有一个权衡,性能方面,它是高效的,注意我们根本不会迭代它们。
  • 无论如何,创建该数组都需要时间,OP 已经迫在眉睫。也许我说错了,OP 关心时间,每一个不必要的动作对 OP 都是有害的,如果你看我的回答,一点类型转换很快就解决了允许响应的问题而不会过火
【解决方案5】:

此解决方案允许您输入任何整数值,甚至是负数。这是您的相同代码,并进行了一些修改,并添加了一个并行数组进行比较。它还删除了一些不再需要的代码行。

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    System.out.print("How many numbers are you going to enter? ");
    int num = scan.nextInt();
    int[] arr = new int[num]; // initialize array with user inputted length
    int[] arrflag = new int[num];
    for (int i = 0; i < arr.length; i++) { // enter numbers into array
        System.out.print("Enter number: ");
        arr[i] = scan.nextInt();
        arrflag[i] = 0;
    }

    int[] unique = new int[arr.length];    //initialize new array that will hold unique values
    int n=0;
    for (int i = 0; i < arr.length; i++) {            
        if (arrflag[i] == 0) {
            unique[n++] = arr[i];
            for (int j = i+1; j < arr.length; j++) {    //check all elements above int i
                if (arr[i] == arr[j]) {                        
                    arrflag[j]=-1;
                }
            }                
        }
    }   
    for (int i = 0; i < n; i++) {
            System.out.println(unique[i]);
    }
}

【讨论】:

    【解决方案6】:

    创建一个所有值都为“.”的并行字符数组每当您找到重复项时,将值设置为字符数组中的“,”。然后仅打印具有相应“。”的数组的值。在字符数组中。

     }
        System.out.println();
        for (int i = 0; i < arr.length; i++) {
            if(a[i]=='.')
                System.out.println(arr[i]);
        }
    }
    

    }

    【讨论】:

      【解决方案7】:

      字符串 [] 示例。

      public static List<String> arrListWithNoDups(String arr[]){
      
          Map<String, Integer>map = new HashMap<String, Integer>();
          List<String>list = new ArrayList<String>();
      
          for(int i = 0; i<arr.length; i++){
              if(map.get(arr[i]) == null){
                  map.put(arr[i], 0);
              }
              else{
                  map.put(arr[i], map.get(arr[i])+1);
              }
          }
      
          for(int j = 0; j<arr.length; j++){
              if(map.get(arr[j])==0){
                  list.add(arr[j]);
              }
          }
      
          return list;
      
      }
      

      【讨论】:

        【解决方案8】:

        公共类 RemoveDuplicateFromArray {

        public static void main(String[] args) {
        
            int[] myArray = {1, 2, 1, 4, 1, 5, 2, 5};
            System.out.println("Before removing duplicate" + Arrays.toString(myArray));
        
            RemoveDuplicateFromArray rd = new RemoveDuplicateFromArray();
            int[] newArray = rd.findDuplicate(myArray);
            System.out.println("Before removing duplicate" + Arrays.toString(newArray));
        }
        
        public int[] findDuplicate(int[] inputArray) {
            Arrays.sort(inputArray);
            int count = 0;
            for (int i = 0; i < inputArray.length; i++) {
                if (i + 1 < inputArray.length && inputArray[i] == inputArray[i + 1]) {
                    count++;
                }
            }
            int[] result = new int[inputArray.length - count];
            int c = 0;
            for (int j = 0; j < inputArray.length; j++) {
                if (j + 1 < inputArray.length && inputArray[j] == inputArray[j + 1]) {
        
                } else {
                    result[c] = inputArray[j];
                    c++;
                }
            }
            inputArray = result;
            return inputArray;
        }
        

        }

        【讨论】:

          【解决方案9】:

          我尝试改进此代码,如果可以进一步改进,请 cmets/suggest。

          public static int[] removeDuplicate(int[] arr) {
              int[] noDuplicates = new int[arr.length];
              for (int i = 0; i < arr.length; i++) {
                  boolean b = true;
          
                  for (int j = i + 1; j < arr.length; j++) {
                      if (arr[i] == arr[j]){
                          b = false;
                      }
                  }
          
                  if (b) {
                      noDuplicates[i] = arr[i];
                      System.out.print(noDuplicates[i] + " ");
                  }
              }
              return noDuplicates;
          

          }

          【讨论】:

            【解决方案10】:
            void myFunction(int arr[])
            {
            
                int size=arr.length;
                for(int i=0;i<size;i++)
                {
                    for(int j=i+1;j<size;j++)
                    {
            
                        if(arr[i]==arr[j])
                        {
                            arr[j]=arr[size-1];
                            size--;
                        }
                    }
                }
            
                for(int a=0;a<size;a++)
                {
                    System.out.print(arr[a]+" ");
                }
            
            }
            

            【讨论】:

            • 虽然代码很受欢迎,但它应该始终有一个附带的解释。这不必很长,但在意料之中。
            • 虽然您的代码实际上似乎完成了问题标题所要求的内容,但它与问题中提供的代码无关。此外,您的答案应始终附有解释,以使不熟悉该主题的人更容易阅读。
            猜你喜欢
            • 2016-10-01
            • 1970-01-01
            • 2021-11-12
            • 2021-01-27
            • 2016-01-24
            • 2022-01-03
            • 1970-01-01
            • 2021-12-12
            • 1970-01-01
            相关资源
            最近更新 更多