【问题标题】:Counting occurrences of integers in an array [duplicate]计算数组中整数的出现次数[重复]
【发布时间】:2015-11-01 04:46:47
【问题描述】:

我正在编写一个程序来计算输入到数组中的整数的出现次数,例如,如果你输入 1 1 1 1 2 1 3 5 2 3,程序会打印出不同的数字,然后是它们的出现次数,就像这样:

1 出现 5 次, 2 出现 2 次, 3 出现 2 次, 5发生1次

几乎完成了,除了一个我想不通的问题:

import java.util.Scanner;
import java.util.Arrays;
public class CountOccurrences
{
   public static void main (String [] args)
   { 

    Scanner scan = new Scanner (System.in);

    final int MAX_NUM = 10;  

    final int MAX_VALUE = 100;

    int [] numList;

    int num;

    int numCount;

    int [] occurrences; 

    int count[];

    String end;

    numList = new int [MAX_NUM];

    occurrences = new int [MAX_NUM];

    count = new int [MAX_NUM];

 do
  {
     System.out.print ("Enter 10 integers between 1 and 100: ");

     for (num = 0; num < MAX_NUM; num++)
     {
        numList[num] = scan.nextInt();
     }

     Arrays.sort(numList);

     count = occurrences (numList); 

     System.out.println();   

     for (num = 0; num < MAX_NUM; num++)
     {
        if (num == 0)
        {
           if (count[num] <= 1)
              System.out.println (numList[num] + " occurs " + count[num] + " time");

           if (count[num] > 1)
              System.out.println (numList[num] + " occurs " + count[num] + " times");
        } 

        if (num > 0 && numList[num] != numList[num - 1])
        {
           if (count[num] <= 1)
              System.out.println (numList[num] + " occurs " + count[num] + " time");

           if (count[num] > 1)
              System.out.println (numList[num] + " occurs " + count[num] + " times");
        }   
     }          

     System.out.print ("\nContinue? <y/n> ");
     end = scan.next(); 

  } while (!end.equalsIgnoreCase("n"));
}


 public static int [] occurrences (int [] list)
 {
      final int MAX_VALUE = 100;

      int num;

      int [] countNum = new int [MAX_VALUE];

      int [] counts = new int [MAX_VALUE];

      for (num = 0; num < list.length; num++)
  {
     counts[num] = countNum[list[num]] += 1;
  }

  return counts;
 } 
}

我遇到的问题是,无论“num”的当前值是多少,“count”都只会打印出 1,而问题不在于计算出现次数的方法,因为当您输入数字时在变量的位置,值会发生变化。

有什么方法可以改变它,以便正确打印出出现的情况,或者我应该尝试其他方法吗? 而且解决方案越简单越好,因为我还没有超越一维数组。

感谢您的帮助!

【问题讨论】:

  • 请以此为契机学习调试。所有 IDE(eclipse、Netbeans、IntellIJ、..)都带有简洁的调试工具。
  • 问题出在你的出现函数中。 counts[num] = countNum[list[num]] += 1; 行没有做你认为它正在做的事情。它在数组中移动,将数字的计数放在单独的索引中。以您当前的输入为例,counts 数组的值为 [1, 2, 3, 4, 5, 1, 2, 1, 2, 1, ... 0]。第一个[1, 2, 3, 4, 5 是因为你的数组中有5 个1,下一个1, 2 是因为你的数组中有2 个2,等等。你需要重写你的occurrences 函数。会留下这个作为答案,但问题已关闭。

标签: java arrays counting


【解决方案1】:

试试 HashMap。对于这种类型的问题,哈希是非常高效和快速的。

我编写了这个函数,它接受数组并返回一个 HashMap,其键是数字,值是该数字的出现。

public static HashMap<Integer, Integer> getRepetitions(int[] testCases) {    
    HashMap<Integer, Integer> numberAppearance = new HashMap<Integer, Integer>();

    for(int n: testCases) {
        if(numberAppearance.containsKey(n)) {
            int counter = numberAppearance.get(n);
            counter = counter+1;
            numberAppearance.put(n, counter);
        } else {
            numberAppearance.put(n, 1);
        }
    }
    return numberAppearance;
}

现在遍历哈希图并打印这样的数字:

HashMap<Integer, Integer> table = getRepetitions(testCases);

for (int key: table.keySet()) {
        System.out.println(key + " occur " + table.get(key) + " times");
}

输出:

【讨论】:

  • 不鼓励使用HashTable。请改用HashMap
  • @MohammadGhazanfar 当你说“气馁”时,你是什么意思?
  • @Smac89 请阅读thisAs of the Java 2 platform v1.2, this class was retrofitted to ...
【解决方案2】:

我会使用 Bag,这是一个统计项目在集合中出现的次数的集合。 Apache Commons 有一个实现。这是他们的interface,这是sorted tree implementation

你会这样做:

Bag<Integer> bag = new TreeBag<Integer>();
for (int i = 0; i < numList.length; i++) {
    bag.add(numList[i]);
}
for (int uniqueNumber: bag.uniqueSet()) {
    System.out.println("Number " + uniqueNumber + " counted " + bag.getCount(uniqueNumber) + " times");
}

上面的示例从numList 数组中获取元素并将它们添加到Bag 以生成计数,但您甚至不需要数组。只需将元素直接添加到Bag。比如:

// Make your bag.
Bag<Integer> bag = new TreeBag<Integer>();

...

// Populate your bag.
for (num = 0; num < MAX_NUM; num++) {
    bag.add(scan.nextInt());
}

...

// Print the counts for each unique item in your bag.
for (int uniqueNumber: bag.uniqueSet()) {
    System.out.println("Number " + uniqueNumber + " counted " + bag.getCount(uniqueNumber) + " times");
}

【讨论】:

    【解决方案3】:

    我要说的是,我花了一段时间才弄清楚countcountNum这两个变量代表什么,也许需要一些cmets。但最后我发现了这个错误。

    假设输入十个数字是:5, 6, 7, 8, 5, 6, 7, 8, 5, 6

    排序后,numList 为:5, 5, 5, 6, 6, 6, 7, 7, 8, 8

    occurrences()返回的数组count应该是:[1, 2, 3, 1, 2, 3, 1, 2, 1, 2]

    实际上,这个结果数组中唯一有用的数字是:

    count[2]: 3     count number for numList[2]: 5
    count[5]: 3     count number for numList[5]: 6
    count[7]: 2     count number for numList[7]: 7
    count[9]: 2     count number for numList[9]: 8
    

    其他数字,例如3 之前的前两个数字1, 2,仅用于增量计算总和,对吗?因此,您的循环逻辑应更改如下:

    1. 删除第一个if代码块:

      if (num == 0)
      {
         if (count[num] <= 1)
            System.out.println (numList[num] + " occurs " + count[num] + " time");
      
         if (count[num] > 1)
            System.out.println (numList[num] + " occurs " + count[num] + " times");
      } 
      
    2. 将第二个if 条件更改为:

      if ((num + 1) == MAX_NUM || numList[num] != numList[num + 1]) {
          ......
      }
      

    在此之后,您的代码应该可以正常运行。

    顺便说一句,你真的不需要这么复杂。试试HashMap :)

    【讨论】:

    • 这正是我需要的,谢谢!下次我有问题时一定会添加 cmets :)
    【解决方案4】:

    您可以从初始化一个介于 MIN 和 MAX 之间的值数组开始。然后,您可以在该值出现时添加到数组的每个元素1。类似的,

    Scanner scan = new Scanner(System.in);
    final int MAX_NUM = 10;
    final int MAX_VALUE = 100;
    final int MIN_VALUE = 1;
    final int SIZE = MAX_VALUE - MIN_VALUE;
    int[] numList = new int[SIZE];
    System.out.printf("Enter %d integers between %d and %d:%n", 
            MAX_NUM, MIN_VALUE, MAX_VALUE);
    for (int i = 0; i < MAX_NUM; i++) {
      System.out.printf("Please enter number %d: ", i + 1);
      System.out.flush();
      if (!scan.hasNextInt()) {
        System.out.printf("%s is not an int%n", scan.nextLine());
        i--;
        continue;
      }
      int v = scan.nextInt();
      if (v < MIN_VALUE || v > MAX_VALUE) {
        System.out.printf("%d is not between %d and %d%n", 
                v, MIN_VALUE, MAX_VALUE);
        continue;
      }
      numList[v - MIN_VALUE]++;
    }
    boolean first = true;
    for (int i = 0; i < SIZE; i++) {
      if (numList[i] > 0) {
        if (!first) {
          System.out.print(", ");
        } else {
          first = false;
        }
        if (numList[i] > 1) {
          System.out.printf("%d occurs %d times", 
                  i + MIN_VALUE, numList[i]);
        } else {
          System.out.printf("%d occurs once", i + MIN_VALUE);
        }
      }
    }
    System.out.println();
    

    1另见radix sort counting sort

    【讨论】:

      【解决方案5】:

      我认为如果您使用这种方法,您可以大大简化您的代码。您仍然需要修改以包含 MAX_NUMMAX_VALUE

      public static void main(String[] args) {
      
          Integer[] array = {1,2,0,3,4,5,6,6,7,8};
          Stack stack = new Stack();
      
          Arrays.sort(array, Collections.reverseOrder());
      
          for(int i : array){
              stack.push(i);
          }
      
          int currentNumber = Integer.parseInt(stack.pop().toString()) , count = 1;
      
          try {
              while (stack.size() >= 0) {
                  if (currentNumber != Integer.parseInt(stack.peek().toString())) {
                      System.out.printf("%d occurs %d times, ", currentNumber, count);
                      currentNumber = Integer.parseInt(stack.pop().toString());
                      count = 1;
                  } else {
                      currentNumber = Integer.parseInt(stack.pop().toString());
                      count++;
                  }
              }
          } catch (EmptyStackException e) {
               System.out.printf("%d occurs %d times.", currentNumber, count);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2016-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-11
        • 2012-11-18
        • 1970-01-01
        相关资源
        最近更新 更多