Hi希望显示随机数组的重复元素,其大小可由用户指定。我在输出中遇到的问题是,该函数正在打印重复的次数与重复的次数相同,但是我只希望打印一次。 这是我的代码和前者之后的输出:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int array_size = 0;
int *my_array;
int i = 0;
printf("Enter the size of the array:\n");
scanf("%d",&array_size);
my_array = malloc(array_size * sizeof my_array[0]);
if(NULL == my_array) {
fprintf(stderr,"MEMORY ALLOLCATION FAILED \n");
return EXIT_FAILURE;
}
for(i=0;i<array_size;i++){
my_array[i] = rand()%array_size;
}
printf("What's in the array:\n");
for(i = 0;i<array_size;i++){
printf("%d ",my_array[i]);
}
printf("\n");
display_repeats(my_array, array_size);
free(my_array);
return EXIT_SUCCESS;
}
void display_repeats(int *a,int n){
int *repeats;
repeats = malloc(n * sizeof repeats[0]);
int i=0;
int j=0;
int count = 0;
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(a[i] == a[j]){
count++;
}
}
if(count>1){
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
count = 0;
}
free(repeats);
}
这是我得到的输出
Enter the size of the array:
5
What's in the array:
3 1 2 0 3
3 occurs 2 times
3 occurs 2 times
我希望“ 3次出现2次”打印一次。 请帮忙!
答案 0 :(得分:2)
正在发生的事情是您的代码意识到3在此块中重复了两次:
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(a[i] == a[j]){
count++;
}
}
if(count>1){
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
}
当i
等于0时,它将查看数组并意识到重复3,因此count>1
将是true
。然后,当i
等于4时,count>1
将再次为true
,并且您会得到两次打印。
为了解决此问题,我将创建一个数组,该数组存储已被验证为重复的数字并进行检查。
答案 1 :(得分:1)
由于您的情况是元素的值 这个想法是存储每个值的计数,并在开始搜索每个新值之前检查以检查是否已被计数。memset(repeats, 0, n*sizeof(repeats[0]));
for(i=0;i<n;i++){
for(j=0;j<n;j++){
count = repeats[a[i]];
if(count>0)
break;
if(a[i] == a[j]){
count++;
}
}
repeats[a[i]] = count;
答案 2 :(得分:0)
尝试一下:
for(i=0;i<n-1;i++)
{
for(j=1;j<n;j++)
{
因此,请勿将同一元素与其自身进行比较。
答案 3 :(得分:0)
在display_repeats()
中,您可以简单地更新2行并添加3行以使您的程序具有正确的行为。我们将在以后看到它:我们可以使用C99语法和逗号C运算符优化最终代码,以编写比原始代码少得多的行(9行而不是20行!)。 >
因此,在此答案中,您将找到如何获得具有正确行为且非常短,比初始代码短的最终代码:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for (int j = i + 1; j < n; j++)
if (a[i] == a[j]) count++, a[j] = -1;
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
这个想法是在计数增加之后,将与前一个匹配的每个数组值设置为-1。因为您不想再次计算该值。
因此只需执行以下操作:
在您写count = 0
的两行中,将0替换为1,因为您确定列表中的每个数字都必须至少计算一次。
这样,您可以避免检查内部循环中i等于j的情况:在计数中已经考虑了它。因此,在内循环的开头添加if (i == j) continue;
。
使用先前的更新,您现在可以确定在内部循环中递增计数时,j不等于i。因此,您可以在数组中更改a[j]
的值而无需更改a[i]
。
因此,在增加计数后立即添加a[j] = -1;
。这样,当我递增以检查新值的新计数时,就不可能已经对新的计数值进行了计数。
最后,您不想计算数组中-1的次数。但是您已将某些值替换为-1。因此,只需在外部循环的开头添加if (a[i] == -1) continue;
即可避免计算数组中-1的数量。
此中间代码是:
void display_repeats(int *a,int n) {
int *repeats;
repeats = malloc(n * sizeof repeats[0]);
int i=0;
int j=0;
int count = 1;
for(i=0; i<n; i++) {
if (a[i] == -1) continue;
for(j=0; j<n; j++) {
if (i == j) continue;
if(a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if(count > 1) {
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
count = 1;
}
free(repeats);
}
现在,我们可以优化此代码。
首先,我们可以避免在j <= i时测试a[i] == a[j]
:如果发生这种情况,我们知道我们之前已经显示了a [j]的计数(a [j]出现的次数在数组中)。因此,我们可以将for (j=0; j < n; j++) {
替换为for (j=i+1; j<n; j++) {
。
通过最后一次更新,我们知道内循环的第一行将永远不会匹配:我不能等于j。因此,我们可以删除此行(if (i == j) continue;
)。
请注意,重复数组中存储的值仅用于获取printf()调用中的count值。因此,我们可以删除对重复数组的所有引用,而只需在printf()调用中使用count。
现在,您可以看到我们将count设置为1,两次。如果不在主循环结束时将其设置为1,则只能执行一次,以准备一个新循环,但要在开始时进行。
现在,请注意i,j和count具有相同的类型,因此只能使用一行来定义它们:int i = 0, j = 0, count = 1;
。而且,i和j稍后在for循环中定义,因此无需在此处定义其初始值。因此,我们可以简单地编写int i, j, count = 1;
。但是现在在外部循环的开始处定义了计数,因此我们无需事先定义它。因此,我们只需要定义i,j并计数而无需初始值:int i, j, count;
。
新的中间代码是:
void display_repeats(int *a, int n) {
int i, j, count;
for (i = 0; i < n; i++) {
if (a[i] == -1) continue;
count = 1;
for(j = i + 1; j < n; j++) {
if (a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
使用C99语法
但是,使用C99规范,我们可以做更多的事情:我们可以使用for指令定义一个变量:我们可以编写for (int i = ...)
。不再需要以前定义它。因此我们可以避免写int i, j, count;
,我们将在初次使用时对其进行定义:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for(int j = i + 1; j < n; j++) {
if (a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
使用逗号C运算符
再次,我们可以做得更好!我们可以使用逗号运算符(,
):它是一个二进制运算符,用于评估其第一个操作数,丢弃结果,评估第二个操作数并返回其值。使用逗号运算符,我们可以将count++; a[j] = -1;
转换为一条指令:a[j] = (count++, -1)
。但是我们可以避免用括号写count++, a[i] = -1
。现在,由于只有一条指令,因此对于if语句不需要块。因此,我们可以删除很多括号。
最终代码是:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for (int j = i + 1; j < n; j++)
if (a[i] == a[j]) count++, a[j] = -1;
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
答案 4 :(得分:0)
谢谢大家,我将其与以上想法结合使用! 这就是我得到的..
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int array_size = 0;
int *my_array;
int i = 0;
printf("Enter the size of the array:\n");
scanf("%d",&array_size);
my_array = malloc(array_size * sizeof my_array[0]);
if(NULL == my_array) {
fprintf(stderr,"MEMORY ALLOLCATION FAILED \n");
return EXIT_FAILURE;
}
for(i=0;i<array_size;i++){
my_array[i] = rand()%array_size;
}
printf("What's in the array:\n");
for(i = 0;i<array_size;i++){
printf("%d ",my_array[i]);
}
printf("\n");
display_repeats(my_array, array_size);
free(my_array);
return EXIT_SUCCESS;
}
void display_repeats(int *a,int n){
int *freq;
freq = malloc(n * sizeof freq[0]);
int i=0;
int j=0;
int count = 0;
for(i=0;i<n;i++){
freq[i] = -1;
}
for(i=0;i<n;i++){
count = 1;
for(j=i+1;j<n;j++){
if(a[i]==a[j]){
count++;
freq[j] = 0;
}
}
if(freq[i]!=0){
freq[i] = count;
}
}
for(i=0;i<n;i++){
if(freq[i]!=1 && freq[i]!=0){
printf("%d occurs %d times\n",a[i],freq[i]);
}
}
free(freq);
}