【问题标题】:Finding Duplicates in Array and printing them only Once在数组中查找重复项并仅打印一次
【发布时间】:2015-07-04 06:21:16
【问题描述】:

我正在尝试遍历我的数组并找到所有重复多次的数字:

例如:如果有1 1 2 3 4

它应该打印出“1重复不止一次”

这是我的代码,到目前为止我已经尝试过,但是它会打印所有重复项并继续运行,如果有 4 4 4 4 3 6 5 6 9,它将打印所有 4,但我不希望这样:

class average {

 public static void main(String[] args) throws IOException {

    int numOfLines = 0;
    int sum = 0, mean = 0, median = 0, lq = 0, uq = 0;
    int[] buffer;

    File myFile = new File("num.txt");
    Scanner Scan = new Scanner(myFile);

    while(Scan.hasNextLine()) {
        Scan.nextLine();
        numOfLines++;
    }
    Scan.close();
    Scan = new Scanner(myFile);

    System.out.println("Number Of Lines: " + numOfLines);

    buffer = new int[numOfLines];

    for(int i=0; i<numOfLines; i++) {
        buffer[i] = Scan.nextInt();
    }
    Scan.close();
    Scan = new Scanner(myFile);

    for(int i=0; i<buffer.length; i++) {
        sum = sum+i;
        mean = sum/numOfLines;
    }
    System.out.println("Sum: " + sum);
    System.out.println("Mean: " + mean);

    for(int i=0; i<buffer.length; i++) {
        for(int k=i+1; k<buffer.length; k++) {
            if(buffer[k] == buffer[i]) {
                System.out.println(buffer[k]);
            }
        }
    }

【问题讨论】:

  • 你可以对数组进行排序吗?
  • 我正在尝试不排序 @Makoto
  • 你能用Set吗?
  • 这很公平。在这种情况下,您是否知道您在读入它们后所拥有的值的范围?也就是说,你知道最小值和最大值吗?在这种情况下,这可以为您提供帮助。
  • @Kon - 没有集合,只是简单的数组

标签: java arrays file for-loop duplicates


【解决方案1】:

使用 apache commons CollectionUtils.getCardinalityMap(collection):

  final Integer[] buffer = {1, 2, 3, 4, 5, 6, 7, 2, 1, 7, 9, 1, 1, 3};
  final List<Integer> list = Arrays.asList(buffer);
  final Map<Integer, Integer> cardinalityMap = CollectionUtils.getCardinalityMap(list);
  for (final Map.Entry<Integer, Integer> entry: cardinalityMap.entrySet()) {
    if (entry.getValue() > 1) {
      System.out.println(entry.getKey());
    }
  }

cardinalityMap的toString()在init之后是这样的:

{1=4, 2=2, 3=2, 4=1, 5=1, 6=1, 7=2, 9=1}

使用标准java

  final Integer[] buffer = {1, 2, 3, 4, 5, 6, 7, 2, 1, 7, 9, 1, 1, 3};
  final List<Integer> list = Arrays.asList(buffer);
  final Set<Integer> set = new LinkedHashSet<Integer>(list);
  for (final Integer element: set) {
    if (Collections.frequency(list, element) > 1) {
      System.out.println(element);
    }
  }

【讨论】:

    【解决方案2】:

    使用集合来解决这个问题要简单得多,而且可能更快。但是,按照这里的要求,这是一个使用“只是简单数组[s]”并且没有排序的答案。我尽量不要过多更改您的代码,但我拒绝在异常情况下泄漏资源。

    import java.io.*;
    import java.util.Arrays;
    import java.util.Scanner;
    
    class Average {
    
         public static void main(String[] args) throws IOException {
    
            int numOfLines = 0;
            int sum = 0, mean = 0, median = 0, lq = 0, uq = 0;
            int[] buffer;
            int flag = -1;
    
            File myFile = new File("num.txt");
            try (Scanner Scan = new Scanner(myFile)) {
    
                while(Scan.hasNextLine()) {
                    Scan.nextLine();
                    numOfLines++;
                }
            }
            try (Scanner Scan = new Scanner(myFile)) {
    
                System.out.println("Number Of Lines: " + numOfLines);
    
                buffer = new int[numOfLines];
    
                for(int i=0; i<numOfLines; i++) {
                    buffer[i] = Scan.nextInt();
                }
            }
    
            for(int i=0; i<buffer.length; i++) {
                sum = sum+i;
                mean = sum/numOfLines;
            }
            System.out.println("Sum: " + sum);
            System.out.println("Mean: " + mean);
    
            //copy every duplicate
            int[] dupesOnly = new int[numOfLines];
            int dupesOnlyIndex = 0;
            for(int i=0; i<buffer.length; i++) {
                for(int k=i+1; k<buffer.length; k++) {
                    if(buffer[k] == buffer[i]) {
                        dupesOnly[dupesOnlyIndex++] = buffer[i];
                        //System.out.println(buffer[k]);
                    }
                }
            }
    
            //mark all but first occurrence of dupe
            boolean[] skip = new boolean[dupesOnlyIndex]; //Inits to false
            for (int i = 0; i < dupesOnlyIndex; i++) {
                for(int k=i+1; k<buffer.length; k++) {
                    if(dupesOnly[k] == dupesOnly[i]) {
                        skip[k] = true;
                    }
                }
            }
    
            //skip elements marked as extra dupes
            int[] dupesUnique = new int[dupesOnlyIndex];
            int dupesUniqueIndex = 0;
            for (int i = 0; i < dupesOnlyIndex; i++) {
                if (skip[i] == false) {
                    dupesUnique[dupesUniqueIndex++] = dupesOnly[i];
                }
            }     
    
            //trim to size
            int[] dupesReport = new int[dupesUniqueIndex];
            for (int i = 0; i < dupesReport.length; i++) {
                dupesReport[i] = dupesUnique[i];
            }
    
            System.out.println("Dupes: " + Arrays.toString(dupesReport));
        }
    }
    

    输入文件“num.txt”(数字由换行符而不是逗号分隔):

    1, 2, 3, 4, 5, 6, 7, 2, 1, 7, 9, 1, 1, 3
    

    输出:

    Number Of Lines: 14
    Sum: 91
    Mean: 6
    Dupes: [1, 2, 3, 7]
    

    【讨论】:

      【解决方案3】:

      只需将您发现重复的数字添加到HashSetHashMap 等结构中,以便以后检测到另一个重复时可以找到它。

      Set<Integer> printed = new HashSet<Integer>();
      
        for(int i=0; i<buffer.length; i++) {
          for(int k=i+1; k<buffer.length; k++) {
            if(buffer[k] == buffer[i]) {
              Integer intObj = new Integer(buffer[k]);
              if (!printed.contains(intObj)) {
                System.out.println(buffer[k]);
                printed.add(intObj);
              }
              break;
             }
          }
        }
      

      更好的 O(n) 算法:

      Set<Integer> printed = new HashSet<Integer>();
      
        for(int i=0; i<buffer.length; i++) {
          if (!printed.add(new Integer(buffer[i])) {
             System.out.println(buffer[i]);
          }
        }
      

      【讨论】:

      • 你有 O(n^2),可以通过消除第二个循环减少到 O(n)。
      • 由于自动装箱,无需创建 Integer 实例 -> printed.Add(buffer[i])
      【解决方案4】:
      Integer[] ints = {1, 1, 2, 3, 4};
      
      System.out.println(new HashSet<Integer>(Arrays.asList(ints)));
      

      输出:[1, 2, 3, 4]

      【讨论】:

        【解决方案5】:

        我会使用HashMap 来存储我在数组中遇到的值,并将计数作为一个值。因此,如果遇到 4,您将在 HashMap 中查找它,如果它不存在,您将添加它的值 1,否则增加返回的值。

        您可以循环 HashMap 并获取所有值并打印数组中遇到的重复项数。

        【讨论】:

          【解决方案6】:

          您对数组的每一项执行检查,包括第一个4、第二个4 等等。这就是为什么它不会停止,它会为每个重复的元素多次打印消息。

          您是说您不能使用Set 并且您不想对数据进行排序。我的建议是循环遍历数组并将每个重复的项目添加到列表中。确保检查该项目是否已添加。 (或使用Set :))

          然后遍历列表并打印这些项目。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-04-29
            • 1970-01-01
            • 2012-05-16
            • 1970-01-01
            • 1970-01-01
            • 2012-09-25
            相关资源
            最近更新 更多