C在数组中找到第二大数字

正如标题所说,我必须在数组中找到第二大数字,如果该数组中的每个数字相等,我应该写它是-∞。 我写了这篇文章,任何人都可以检查一下我是否可以更好地优化它? 这个数组只是一个例子,它应该是x [1 … n]但是因为我必须将它重写为伪代码,所以我把它作为一个例子

#include  int main() { int x[7]={90,90,78,41,21,27,35}; int i, max, secmax, y; secmax=0; max=x[0]; for(i=1;imax) { secmax=max; max=x[i]; } else if (x[i]>secmax&&x[i]<max) { secmax=x[i]; } } for(i=0;i<7;i++) if(x[i]==x[i+1]) y++; if (y==6) printf("sec max to minus nieskonczonosc \n"); else printf("max to %da secmax to %d\n",max,secmax); return 0; } 

这是你可以做的:

 int get_second_max(int *x, size_t n) { int max[2] = {-MAX_INT,-MAX_INT}; int i = 0, same = 1; if (NULL == x || 0 == n) return -MAX_INT; max[0] = x[0]; max[1] = x[0]; for(i = 1; i < n; i++) { /* same is used to check * if the array contains * the same number all along. */ same &= (x[i] == x[i-1]); /* At the i-th iteration : * -> max[0] stores the maximum value * -> max[1] stores the second maximum value */ /* We hit a new max value, we must : * 1. Update the second max value with the current max value * 2. Update the current max value with the new max we found */ if(x[i] > max[0]) { max[1] = max[0]; max[0] = x[i]; } else if(x[i] > max[1]) { max[1] = x[i]; } } if(same) { return -MAX_INT; } else { return max[1]; } } 

您可以通过将secmax最初设置为负无穷大来避免对整个arrays进行最后一次扫描。 这样它将始终具有正确的值。

此外,您的代码中存在错误: i<=7应替换为i < sizeof(x)/sizeof(x[0]) 。 否则你的x[i]会给你一个段错误。

我做了一些修改并添加了一些评论。 下面的代码讨论。

 #include  // for INT_MIN macro #include  int main() { // Let the compiler count length of array. // -- declare "x[]", no need to specify length const int x[] = { 90, 90, 78, 41, 21, 27, 35 }; // -- use sizeof() math to find length of array // -- use const int rather than #define so debugger can see value const int len = sizeof(x) / sizeof(x[0]); int i, max, secmax, same_count; if (0 == len) { // zero-length list: return INT_MIN printf("sec max to minus nieskonczonosc: %d\n", INT_MIN); return 0; } secmax = max = INT_MIN; same_count = 0; // start loop at 0 for(i = 0; i < len; ++i) { // We'll use the same idea you originally used to find if all values were // the same, but do it as part of the same loop. No need to loop over // the values twice. For a short list, looping twice is not a big deal, // but for really large data sets it will save lots of time to do it this way. same_count += (x[0] == x[i]); if (x[i]>max) { // Found value greater than current max; shift max down to secmax // and save new max value. secmax=max; max=x[i]; } else if (x[i]>secmax && x[i] 

我们没有太多办法来改善运行时间。 您的代码已经在直接找到所需的值。

我们可以做的一件事就是通过在第一个循环中完成它的工作来摆脱你的第二个循环。

@Rerito的答案改变了算法:不是计算有多少值相同,而是查看计数是否与长度匹配,该答案从1位开始,并使用按位“和”进行值比较。 如果比较失败,则比较结果将为零,并且值为0的按位“和”结果为0.因此,如果比较失败,则将初始1位清零为0位,循环结束,如果仍然设置了1位,则每个值必须相同。

我保留了计算多少个值相同的基本算法,然后检查计数是否与长度匹配。 我重命名了计数变量,因为名称y没有信息,我将计数更新移动到第一个循环内部(然后摆脱了第二个循环),我重新编写代码,以便您可以更改数组值,它应该全部工作。

通过代码散布未连接的“魔法”值是不好的做法。 你的原始代码有三个位置的7个和一个6 ...因此当有人改变数组的长度时,它会为一个bug打开。 我的代码让C编译器计算数组中有多少个值,设置一个常量( len ),然后专门使用该常量。 因此,您可以简单地在数组中添加或删除值,并且更改的代码仍然可以正常工作。

编辑:@sds写道:“你可以通过将secmax最初设置为负无穷大来避免整个arrays的最后一次扫描。这样它总是具有正确的值。”

哇,他是对的! 我们所要做的就是将secmax设置为我们想要返回的值,如果每个值都相同,因为当代码看到小于max的值时,代码被写入仅设置secmax ,并且每个值都相同,那么secmax永远不会改变。