簡體   English   中英

如何在給定的數字集合中找到第二大元素?

[英]How do i find the second largest element among given collection of numbers?

在不使用數組的情況下,我正在嘗試執行此操作。 我的代碼有什么問題?

n是元素數,a是第一個元素(假定最初最大),b每次存儲新元素,sec變量存儲第二大元素。 數字都是正數。 這是來自在線競賽。

#include<stdio.h> 
int main() { 
    int i,a,b,max,n,sec;
    scanf("%d",&n); 
    scanf("%d",&a); 
    max=a;
    while(n-1!=0) { 
        scanf("%d",&b);
        if(b>max) {
            sec=max;
            max=b;
        }

        else if(b<max && b>sec)
            sec=b;
        else{}
        n--;
    }  

    printf("%d",sec);

    return 0; 
}

在一些測試用例中得到錯誤答案(我不知道)

讓我們看一下輸入

2 4 3

輸入數是二。
4在結束max
3結束於b
b不大於max ,if不執行任何操作。
b小於max,但b不一定大於sec
因為sec在這一點上可以是任何東西-無論該未初始化變量內部當前是什么。 例如,此時的sec不能保證為0。因此else if不觸發,我們將以else {}結尾。

因此,我們最終在程序末尾以尚未初始化的sec執行printf() 這不可能使法官滿意。

要解決此問題,您需要初始化sec 初始化為0可能有用,但是實際上您需要使用盡可能低的輸入值。
因為您選擇了int ,而不是unsigned int ,所以我認為0不是可能的最小值。 但是您必須引用分配/挑戰才能確定可能的最低值。 因此,您需要親自找出答案以編寫解決方案代碼。

另外,您可以分析第一個輸入值以初始化maxsec (需要觀察它們的輸入,直到獲得兩個不同的值;記入Aconcagua)。
但是,通常通常更容易根據需求確定最低的可能值,或者根據環境確定最低的int值。
在某種程度的挑剔中,無論如何,您都需要知道盡可能低的值,以便為實現選擇正確的數據類型。 即,即使分析了前兩個值,您也可能無法選擇最窄的數據類型。

如果您“成功”(根據挑戰判斷)使用0初始化sec ,請嘗試輸入2 1 -1
它應該失敗。
然后嘗試在挑戰/任務說明中找到允許使用0的原因。 它應該在那里,否則找到其他挑戰站點來提高您的編碼技能。

考慮序列2、12、10(省略了周圍的代碼):

int sec;       // unitialised!!!
max = a;       // 12
if(b > max)    // b got 10, so false!
{
    sec = max; // this code is not hit! (b remains uninitalised)
    max = b;
}
else if(b < max && b > sec)
//                      ^ comparing against uninitialised
//                        -> UNDEFINED BEHAVIOUR

您需要適當地初始化sec ,例如使用INT_MIN (在<limits.h>定義); 這是最小允許值,有32位int那將是-2值32 - 1,即-2 147 483 648件不可思議的事有人會輸入這個值,所以你可以使用它作為定點。

您甚至可以使用該值初始化max ,然后就不需要對第一個值進行特殊處理:

int sec = INT_MIN, max = INT_MIN;
int n;
scanf("%d", &n); // you should check the return value, which is number of
                 // successfully scanned values, i. e. 1 in given case,
                 // to catch invalid user input!
// you might check value of n for being out of valid range, at very least < 0

while(n--) // you can do the decrement inside loop header already...
{
    // keep scope of variables as local as possible:
    int a;
    // scanf and comparisons as you had already
    // again don't forget to check scanf's return value
}
if(sec == INT_MAX)
{
    // likely hasn't been modified -> error, no second largest element
}
else
{
    // ...
}

現在,如果您確實希望用戶提供INT_MIN的值作為輸入呢?

您可以有一個單獨的計數器,初始化為0,然后在循環中的兩個if分支中都增加一個; 如果該計數器在循環后小於2,則您至少沒有得到兩個不同的數字...

我喜歡OP如何使用第一個輸入值初始化max

這使我想到可以在幾sec內完成相同的操作。 max的值很好地指示了無法確定sec包含什么max 。在常規情況下, maxsec永遠不能相等。)

因此,一種可能性是用第一個輸入初始化max sec ,並使用max != sec作為指示,是否以后再寫入sec

演示:

#include <stdio.h>

int main()
{
  /* read number of inputs */
  int n;
  if (scanf("%d", &n) != 1 || n < 1) {
    fprintf(stderr, "ERROR!\n");
    return -1;
  }
  /* read 1st input */
  int max;
  if (scanf("%d", &max) != 1) {
    fprintf(stderr, "ERROR!\n");
    return -1;
  }
  --n;
  int sec = max;
  /* read other input */
  while (n--) {
    int a;
    if (scanf("%d", &a) != 1) {
      fprintf(stderr, "ERROR!\n");
      return -1;
    }
    if (max < a) { sec = max; max = a; }
    else if (sec == max || (sec < a && a < max)) sec = a;
  }
  /* evaluate result */
  if (sec == max) {
    puts("No second largest value occurred!\n");
  } else printf("%d\n", sec);
  /* done */
  return 0;
}

輸出:

$ gcc -std=c11 -O2 -Wall -pedantic main.c
$ echo -e "3 3 4 5" | ./a.out
4
$ echo -e "3 3 5 4" | ./a.out
4
$ echo -e "3 4 3 5" | ./a.out
4
$ echo -e "3 4 5 3" | ./a.out
4
$ echo -e "3 5 3 4" | ./a.out
4
$ echo -e "3 5 4 3" | ./a.out
4
$ # edge case:
$ echo -e "2 3 3" | ./a.out
No second largest value occurred!

在coliru上進行現場演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM