C语言 在数组中查找第二个最大的数

rslzwgfq  于 2023-10-16  发布在  其他
关注(0)|答案(4)|浏览(88)

正如标题所说,我必须找到数组中第二大的数字,如果数组中的每个数字都相等,我应该写它是-∞。我写了这个,有人能检查一下,看看我是否可以优化得更好一点吗?这个数组只是一个例子,它应该是x[1.n],但由于我必须将其重写为伪代码,因此我将其作为示例

#include <stdio.h>
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;i<=7;i++)
        {
        if (x[i]>max)
            {
            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 %d a secmax to %d\n",max,secmax);
    return 0;
}
x9ybnkn6

x9ybnkn61#

以下是您可以执行的操作:

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];
    }
}
g52tjvyc

g52tjvyc2#

您可以通过将secmax初始设置为负无穷大来避免整个数组的最后一次扫描。这样,它将始终具有正确的值。
另外,你的代码中有一个bug:i<=7应替换为i < sizeof(x)/sizeof(x[0])。否则你的x[i]将给你一个给予segfault。

wwwo4jvm

wwwo4jvm3#

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

#include <limits.h> // for INT_MIN macro
#include <stdio.h>
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]<max)
            {
            // It wasn't greater than max, but is greater than secmax.
            // Save new secmax value.
            secmax=x[i];
            }
        }

    if (len == same_count)
        printf("sec max to minus nieskonczonosc: %d\n", INT_MIN);
    else 
        printf("max to %d a secmax to %d\n",max,secmax);

    return 0;
}

我们无法做太多事情来改善运行时间。您的代码已经在做查找所需值的简单工作。
我们可以做的一件事是摆脱你的第二个循环,在第一个循环中完成它的工作。
@Rerito的回答改变了算法:这个答案不是计算有多少个值是相同的,也不是查看计数器是否与长度匹配,而是从1位开始,并使用按位的“与”进行值比较。如果比较失败,比较结果将为零,按位“与”的值为0,结果为0。因此,如果比较失败,则初始1位被清除为0位,并且当循环结束时,如果该1位仍然被设置,则每个值必须相同。
我保留了你的基本算法,即计算有多少个值是相同的,然后检查计数是否与长度匹配。我重命名了计数变量,因为名称y没有任何信息,我将计数更新移动到第一个循环中(然后摆脱了第二个循环),我重新编写了代码,以便您可以更改数组值,它应该都可以工作。
在代码中散布不相关的“神奇”值是不好的做法。您的原始代码在三个地方有一个7和一个6.因此,当有人改变数组的长度时,它就为bug敞开了大门。我的代码让C编译器计算数组中有多少个值,设置一个常量(len),然后独占地使用这个常量。因此,您可以简单地添加或删除数组中的值,更改后的代码仍然可以正常工作。
编辑:@sds写道:“您可以通过将secmax初始设置为负无穷大来避免整个阵列的最后一次扫描。这样,它将始终具有正确的值。”
他说得对!我们所要做的就是将secmax设置为我们想要返回的值,如果每个值都是相同的,因为代码只在看到小于max的值时才被写入设置secmax,如果每个值都是相同的,那么secmax永远不会改变。

lstz6jyr

lstz6jyr4#

In my code I am replacing the largest number to zero in the array after printing it, this way we have removed the largest. Then using the new array to find the second largest number. This code is beginner friendly and easy to understand  
// Program to print second largest number
#include<stdio.h>
int main()
{
    int num[10],n,i,largest,second;
    printf("Enter n: ");
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        printf("Enter num %d: ",i+1);
        scanf("%d",&num[i]);
    }
    largest = num[0];
    for(i=1;i<n;i++)
    {
        if(largest<num[i])
         largest = num[i];
    }
    printf("The largest is %d\n",largest);
    for(i=0;i<n;i++)
    {
        if(largest == num[i])
        {
            num[i] = 0;
        }
    }
    printf("Array is: \n");
    for(i=0;i<n;i++)
    {
                                                                                                        printf("%d\t",num[i]);
    }
    second = num[0];
    for(i=1;i<n;i++)
    {
        if(second<num[i])
          second = num[i];
 
    }
    printf("The second largest is %d",second);
    return 0;
}

相关问题