-1

我正在尝试计算数组中整数的出现次数。通过将我在网上找到的一些代码拼凑起来,我能够让它工作,但我真的不明白它为什么工作。我所拥有的是:

int[] hand = {2, 4, 3, 2, 4};
int[] numOccurence = new int[hand.length];


    for (int i = 0; i < hand.length; i++)
        numOccurence[hand[i]]++;

    for (int i = 1; i < numOccurence.length; i++)
        if (numOccurence[i] > 0)
            System.out.println("The number " + i + " occurs " + numOccurence[i] + " times.");

输出为:数字 2 出现 2 次。数字 3 出现 1 次。数字 4 出现 2 次。

此代码如何正确计算出现次数?我不明白它是如何做到这一点的。先感谢您!

4

7 回答 7

3

这只是工作,因为你有一个好运气。尝试在手数组中创建第二个元素,5看看会发生什么。这是因为当前索引处的数字hand被视为数组的索引numOccurence。如果数字大于或等于 的长度numOccurence,您将得到ArrayIndexOutOfBoundsException.

因此,您可以更好地使用 a Map,其中键是数字,值可能是它的计数。

像这样的东西: -

Map<Integer, Integer> numOccurence = new HashMap<Integer, Integer>();
for (int i = 0; i < hand.length; i++) {
    int cnt = 1;
    if (numOccurence.containsKey(hand[i])) {
        cnt = numOccurence.get(hand[i]);
        cnt++;
    }
    numOccurence.put(hand[i], cnt);
}
于 2013-09-12T08:15:42.993 回答
3

此代码实际上不起作用。至少它适用于作者的用例,但可能不适用于您的用例。

尝试使用{2, 4, 99, 2, 4};ashand会失败。

作者将找到的数字hand作为数组的索引numOccurencenumOccurence具有以下结构: {nb occ of 0 ; nb occs 为1 ;...; nb occs 为4 }。这里 99 将超出范围。

于 2013-09-12T08:15:45.990 回答
1

创建数组时

int[] numOccurence = new int[hand.length];

它由它们的默认值填充。对于原始 int,此值为 0。

这当然只有在手包含的数字小于或等于数组的最大索引(长度-1)时才有效,否则它是 ArrayIndexOutOfBound 先生!

于 2013-09-12T08:15:46.413 回答
0

实际上这是为图片创建直方图的相同方法;)

您创建一个表格,您将在其中收集事件。numOccurence[0] 将存储 0 的数量 numOccurence[1] 将存储 1 的数量等。

这就是这样做的

for (int i = 0; i < hand.length; i++)
    numOccurence[hand[i]]++;

在对应于数字 hand[i] 的情况下,它将值加 1

所以如果你先一步一步看这个,他会用 hand[0] = 2 所以他会放

numOccurence[2] = numOccurence[2] + 1 ;

这与(但写起来更快)相同

numOccurence[2]++; 
于 2013-09-12T08:15:17.660 回答
0

这种执行计数的方式称为计数排序

计数排序的优点是它的速度。缺点是对大数字进行排序时需要内存。

代码中有一个错误:

int[] numOccurence = new int[hand.length];

numOccurence需要与列表中的最高数字一样长(而不是列表中的数字数量)。尝试将其中一个数字更改为15,您将得到一个例外。

于 2013-09-12T08:17:54.090 回答
0

首先代码是错误的。您应该将数组的大小设置为数组 + 1numOccurence中的最大值hand。例如:

int[] hand = {2, 100};
int[] numOccurence[] = new int[101];

(您显然应该以编程方式找到最大数量)

现在让我们看一下算法。它从数组中获取每个数字hand,将其视为numOccurence索引值,并将数组中该索引处的数字增加 1 hand。请注意,numOccurence数组的所有元素0默认情况下都在开头。

int[] hand = {2, 4, 3, 2, 4};
int[] numOccurence = new int[5];

脚步:

i = 0hand(什么也没发生,因为数组中没有 0 )

i = 1(情况与 0 相同)

i = 2(数组中有两个2数字hand,所以我们做numOccurence[2] += 1了两次运算,结果是0 + 1 + 1 = 2。所以我们得到了numOccurence[2] = 2

它继续从数组中的所有数字0到最大数字(这里:) 。hand100

于 2013-09-12T08:20:03.540 回答
0

代码遍历给定的数组hand。它将遇到的每个值作为数组的索引numOccurrence。对于 中的每个数字n,这将与 中发生hand的频率完全相同,并且每次发生这种情况时, 的第 th 个元素将递增。nhandnnumOccurrence

因此numOccurrence实际上是一个计数器数组(假设数组元素用 初始化0)。

这种方法的缺点:

  • 分配的计数器数量取决于hand数组中数字的大小。
  • 如果hand数组中的数字分布稀疏,则大多数分配的空间都不会被使用。

选择

您可以通过先排序来改进代码hands。在排序后的数组中,给定数字的所有出现的索引都是连续的,因此您只需扫描排序后的数组就需要一个计数器来编译频率。

于 2013-09-12T08:20:30.460 回答