给定一个正整数列表,找到第二大整数。
注意: 禁止使用数组(只有允许循环之前的概念
这是我的代码:
#include <stdio.h>
#include <limits.h>
int main(){
int N, x, i, max2; //N = total no. of given numbers
int max = INT_MIN;
scanf("%d", &N);
for (i = 1; i <= N; i++) {
scanf("%d", &x);
if (x >= max)
max = x;
else
continue;
}
for (i = 1; i <= N; i++) {
scanf("%d", &x);
if (x == max)
continue;
else if (x < max) {
int max2 = INT_MIN;
if (x >= max2)
max2 = x;
}
printf("2nd largest no.= %d", max2);
}
return 0;
}
这就是我所做的,但没有按预期工作,尽管没有抛出任何错误。基本上,我首先从给定的数字列表中找到最大的数字,然后我试图从剩余的数字中找到最大的数字
我应该对此代码进行哪些更改? 也请提出一个更好的方法来解决这个问题(如果有的话)。
你的方法不起作用:
你不能解析输入两次。即使您发出
rewind(stdin)
,它也只会在输入从文件重定向时起作用,而不是当输入来自字符设备(例如终端)或管道时。您应该修改第一个循环以跟踪 2 个最大值。
max2
未初始化。
在
max2
块的范围内定义了一个新变量if (x < max) {}
,隐藏了外部变量(技术术语是shadowing)。外部变量永远不会改变。
这里是修改版:
#include <stdio.h>
#include <limits.h>
int main(vois) {
int N, x, i;
int max = INT_MIN;
int max2 = INT_MIN;
int has_max = 0;
int has_max2 = 0;
if (scanf("%d", &N) != 1)
return 1;
for (i = 0; i < N; i++) {
if (scanf("%d", &x) != 1)
break;
if (!has_max || x > max) {
has_max = 1;
if (!has_max2) {
has_max2 = 1;
max2 = max;
}
max = x;
} else
if (!has_max2 || x > max2) {
has_max2 = 1;
max2 = x;
}
}
if (has_max2) {
printf("2nd largest no.= %d\n", max2);
} else {
printf("no 2nd largest\n");
}
return 0;
}
您的代码至少是错误的,因为您只需要使用一个输入数据序列,因此只需要一个 for 循环。
注意这个声明
printf("2nd largest no.= %d", max2);
使用了在外部块作用域中声明的变量
max2
int N, x, i, max2; //N = total no. of given numbers
和这个复合语句声明的变量
max2
不一样
else if (x < max) {
int max2 = INT_MIN;
if (x >= max2)
max2 = x;
}
所以在
printf
的调用中,将使用在外部块作用域中声明的未初始化变量 max2
。
当假设第二大数不等于第一大数时,发现第二大数才有意义。
这里有一个解决问题的演示程序
#include <stdio.h>
int main( void )
{
unsigned int n;
if (scanf( "%u", &n ) == 1)
{
int first_max, second_max;
int second_max_exists = 0;
int value;
for (unsigned int i = 0; i < n && scanf( "%d", &value ) == 1; i++)
{
if (i == 0)
{
first_max = value;
}
else if (first_max < value)
{
second_max = first_max;
second_max_exists = 1;
first_max = value;
}
else if (( value != first_max ) && ( ( second_max_exists == 0 ) || ( second_max < value ) ))
{
second_max = value;
second_max_exists = 1;
}
}
if ( second_max_exists ) printf( "2nd largest no.= %d\n", second_max );
else puts( "There is no 2nd largest no." );
}
}
程序输出可能看起来像
10
1 1 1 2 3 3 4 5 7 7
2nd largest no.= 5
的确,第一大数等于
7
,第二大数等于5
。
这里是一个使用swap来保证max是最大的数,max2是第二大的实现。它还确保我们至少对 2 个数字进行操作。
#include <stdio.h>
#include <limits.h>
void swap(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
int main() {
int n;
printf("n? ");
if(scanf("%d", &n) != 1) {
printf("scanf failed\n");
return 1;
}
if(n < 2) {
printf("n >= 2");
return 1;
}
int max;
int max2;
for(int i = 0; i < n; i++) {
int v;
if(scanf("%d", &v) != 1) {
printf("scanf failed\n");
return 1;
}
if(i == 0)
max = v;
else if(i == 1) {
max2 = v;
if(max < max2)
swap(&max, &max2);
} else if(v > max2) {
swap(&v, &max2);
if(max < max2)
swap(&max, &max2);
}
}
printf("2nd largest: %d\n", max2);
}