在OJ网站上做题时经常出现一种情况,那就是题会做,但是不知道多组输入如何处理,导致无法AC。
本文对ACM模式下C语言和Python的测试用例的输入方式进行了系统的整理。
ACM模式VS核心代码模式
有些企业是在牛客上进行面试,有些企业是在力扣上进行面试,两个平台答题模式是有区别的,所以搞懂不同的输入代码模式是很重要的。
ACM输入模式:在这种模式下,你需要自己构造输入数据格式,把要需要处理的容器填充好,OJ不会给你任何代码,你需要自己导入所需的库,定义数据结构,读取和解析输入数据,然后根据题目要求输出结果,最后也要自己根据题目提示控制返回数据的格式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <iostream> #include <vector> using namespace std;
int main() { int n; cin >> n; vector<int> nums(n); for (int i = 0; i < n; i++) { cin >> nums[i]; } return 0; }
|
LeetCode 的核心代码模式:在这种模式下,LeetCode 已经为你处理了输入数据,将其封装在了特定的数据结构中(如数组、链表、二叉树等)。你只需要关注如何实现题目要求的算法逻辑,不需要处理输入和输出。这种模式下,你可以更专注于算法本身,但对于数据结构和输入输出的处理则有所限制。
1 2 3 4 5 6
| class Solution { public: int someFunction(vector<int>& nums) { } };
|
可以看出ACM模式要比核心代码模式多写不少代码,相对来说ACM模式更锻炼代码能力,而核心代码模式是把侧重点完全放在算法逻辑上。
OJ系统中C语言各种输入方式
ACM模式要求写出来的代码是直接可以本地运行的,所以我们需要自己写include哪些库函数,构造输入用例,构造输出用例,因此在OJ网站上做题时经常出现一种情况,那就是题会做,但是不知道多组输入如何处理,导致无法AC。
输入一个数,并原样输出,测试数据有多组:
1 2 3 4
| while(scanf(“%d”,&a)!=EOF) { printf(“%d\n”,a); }
|
先输入一个n,后输入一个共n个数的数组,输出这个数组:
1 2 3 4 5
| scanf(“%d”,&n); for(i=0;i<n;i++) { scanf(“%d”,&a[i]); }
|
先输入一个n后输入一个共n个数的数组,最后在跟一个数X,在这n个数中查找x:
1 2 3 4 5 6
| scanf(“%d”,&n); for(i=0;i<n;i++) { scanf(“%d”,&a[i]); } scanf(“%d”,&x);
|
输入一组数,以0为结束标志:
1
| while(scanf(“%d”,&n),n!=0)
|
示例1:输入一个数x再原样输出,测试数据有多组,以0为结束标志:
1 2 3 4 5 6 7 8 9
| #include<stdio.h> int main() { int x; while(scanf("%d",&x),x!=0) { printf("%d\n",x); } }
|
示例2:输入一个数组并原样输出,先输入一个n代表数组有n个数,测试数据有多组,以输入的n=0时为结束标志:
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include<stdio.h> int main() { int n,a[10],i; while(scanf("%d",&n),n!=0) { for(i=0;i<n;i++) scanf("%d",&a[i]); for(i=0;i<n;i++) printf("%d ",a[i]); printf("\n"); } }
|
二维数组的输入方式:第一行输入一个n,代表接下来输入一个n*n的二维矩阵:
1 2 3 4
| scanf(“%d”,&n); for(i=0;i<n;i++) for(j=0;j<n;j++) scanf(“%d”,&a[i][j]);
|
示例:输入一个二维数组并原样输出,测试数据有多组:
注意:每输入一组数据,按一次回车并输出一组的结果,然后再输入下一组测试数据再按回车再输出下一组的结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include<stdio.h> int main() { int n,i,j,a[10][10]; while(scanf("%d",&n)!=EOF) { for(i=0;i<n;i++) for(j=0;j<n;j++) scanf("%d",&a[i][j]); for(i=0;i<n;i++) { for(j=0;j<n;j++) { printf("%d",a[i][j]); if(j!=n-1) printf(" "); } printf("\n"); } } }
|
末尾加char()
1 2 3 4
| while(scanf(“%c”,&c)!=EOF) { 末尾加getchar(); }
|
示例:输入一个字符,并判断字符串类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include<stdio.h> int main() { char c; while(scanf("%c",&c)!=EOF) { if(c>='a'&&c<='z'||c>='A'&&c<='Z') printf("alpha\n"); else if(c>='0'&&c<='9') printf("numeric\n"); else printf("other\n"); getchar(); } }
|
字符串中不带空格
1 2 3 4
| while(scanf(“%s”,&str)!=EOF) {
}
|
示例:判断不含空格的字符串是由为回文串:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include<stdio.h> #include<string.h> int main() { char s[100]; int x,u,i; while(scanf("%s",s)!=EOF) { x=strlen(s); for(i=0;i<x;i++) { if(s[i]!=s[x-1-i]) { u=0;break; } if(s[i]==s[x-1-i]) { u=1; } } if(u==1) printf("Yes\n"); else if(u==0) printf("No\n"); } }
|
输入不含空格的字符串数组
1 2
| for(i=0;i<n;i++) scanf("%s",s[i]);
|
示例:输入一个n,后面跟n个无空格字符串,(相邻字符串要用空格隔开),输出字符串长度,测试数据有多组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include<string.h> #include<stdio.h> int main() { int n,i,j; while(scanf("%d",&n)!=EOF) { int a[20]={0}; char s[20][60]; for(i=0;i<n;i++) scanf("%s",s[i]); for(i=0;i<n;i++) { a[i]=strlen(s[i]); } for(i=0;i<n;i++) { printf("%s",s[i]);printf("%d\n",a[i]); } } }
|
带空格的字符串
1 2 3 4
| while(gets(str)!=NULL) {
}
|
示例:判断多组含空格的字符串是否为回文串:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include<stdio.h> #include<string.h> int main() { char s[100]; int x,u,i; while(gets(s)!=NULL) { x=strlen(s); for(i=0;i<x;i++) { if(s[i]!=s[x-1-i]) { u=0;break; } if(s[i]==s[x-1-i]) { u=1; } } if(u==1) printf("Yes\n"); else if(u==0) printf("No\n"); } }
|
输入字符串数组(含空格)
1 2
| for(i=0;i<n:i++) gets(s[i]);
|
示例:计算几行字符串的长度,第一行输入n,下面n行每一行输入一个含空格的字符串:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include<string.h> #include<stdio.h> int main() { int n,i,j; char s[20][60]; while(scanf("%d",&n)!=EOF) { int a[20]={0}; for(i=0;i<n;i++) gets(s[i]); for(i=0;i<n;i++) { a[i]=strlen(s[i]); } for(i=0;i<n;i++) { printf("%d\n",a[i]); } } }
|
测试数据有T组,先输入一个组数T,接下来每一行第一个数为每组数的个数n,n的后面再跟n个数:
1 2 3 4 5 6 7
| scanf(“%d\n”,&T); while(T--) { scanf(“%d”,&n); for(i=0;i<n;i++) scanf(“%d”,&a[i]); }
|
示例:输入一个一维数组,并原样输出,先输入一个T,代表有T组测试数据,下面T行每行第一个数n代表每个数组的元素个数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include<stdio.h> int main() { int n,i,a[10],T; scanf(“%d”,&T); while(T--) { scanf("%d",&n); for(i=0;i<n;i++) scanf("%d",&a[i]); for(i=0;i<n;i++) printf("%d ",a[i]); printf("\n"); } }
|
OJ系统中Python的多行输入
在线判题系统(Online Judge)的多行输入问题分为定行输入与不定行输入。
若为定行输入,使用循环+input()即可解决。
若为不定行输入,还要看是否有输入结束的标志。
若不定行输入带结束标志,最简单的方法,使用while循环加结束判断语句即可。
若不定行输入不带结束标志,我们应当使用系统输入sys.stdin较为方便,也可使用其他方法。
这里要注意一点,不定行输入不带结束标志问题,在本地IDE上测试时,输入是自己定义的,输入结束你可以疯狂按回车键,如果你通过判断输入是否为空作为跳出循环的判断语句,你的代码可能可以运行正确,但是在OJ里这种判断方法是错误的,是不可取的。
不定行输入有结束标志示例
题目描述 计算a+b
输入描述: 输入包括两个正整数a,b(1 <= a, b <= 10^9),输入数据有多组, 如果输入为0 0则结束输入
输出描述: 输出a+b的结果
示例:
输入
1 5
10 20
0 0
输出
6
30
方法1:sys.stdin
1 2 3 4 5
| import sys for line in sys.stdin: x,y = map(int, line.split()) if x or y: print(x+y)
|
注意:使用while循环时,必须加循环结束语句以保证一定能跳出循环,否则OJ不通过。
1 2 3 4 5
| while True: x,y = map(int, input().split()) if x == 0 and y == 0: break print(x+y)
|
不定行输入无结束标志示例
题目描述 计算a+b
输入描述: 输入包括两个正整数a,b(1 <= a, b <= 10^9),输入数据有多组, 如果输入为0 0则结束输入
输出描述: 输出a+b的结果
示例:
输入
1 5
10 20
0 0
输出
6
30
方法1:sys.stdin
1 2 3 4
| import sys for line in sys.stdin: a,b = map(int, line.split()) print(a+b)
|
多行输入没有结束标志时,若使用while循环,我们应当使用try,except语句。如下:
1 2 3 4 5 6
| while True: try: a,b = map(int,input().split()) print(a+b) except: break
|
通过判断输入是否为空作为跳出循环的判断语句,是错误的,如下:
1 2 3 4 5 6 7
| while True: line = input() if line == '': break else: a,b = map(int,line.split()) print(a+b)
|
代码样例
输入为int
- 输入包括两个正整数a和b,输入数据包含多组。
1 2 3 4 5 6
| import sys line = sys.stdin.readlines()
for line in lines: numlist = list(map(int, line.split())) print(sum(numlist))
|
- 输入第一行包括一个数据组数t,接下来每行包括两个正整数a,b,求a+b的结果。
1 2 3 4 5 6
| import sys lines = sys.stdin.readlines() n = int(lines[0]) for i in range(n): numList = list(map(int, lines[i+1].split())) print(sum(numList))
|
- 输入包括两个正整数a,b,输入数据有多组,如果输入为0,则结束输入。
1 2 3 4 5 6
| while True: a,b = map(int,input().split()) if a== 0 and b == 0: break else: print(a+b)
|
- 计算一系列数的和,输入包括多组数据。每组数据一行,每行的第一个整数为整数的个数n,n为0得时候结束输入。接下来的n个正整数,即需要求和的每个正整数。
1 2 3 4 5
| while True: a = [int(each) for each in input().split()] if a[0]==0: break print(sum(a[1:]))
|
- 计算一系列数的和,输入的第一行包括一个正整数t,表示数据组数。接下来的t行,每行一组数据。每行的第一个整数为整数的个数n,接下来的n个正整数,即需要求和的每个正整数。
1 2 3 4
| n = int(input()) for _ in range(n): numList = list(map(int, input().split())) print(sum(numList[1:]))
|
- 计算一系列数的和,输入数据有多组,每行表示一组输入数据。每行的第一个整数为整数的个数n。接下来的n个正整数,即需要求和的每个正整数。
1 2 3 4 5
| import sys lines = sys.stdin.readlines() for line in lines: numList = list(map(int, line.split())) print(sum(numList[1:]))
|
- 计算一系列数的和,输入数据有多组,每行表示一组输入数据。每行不定有n个整数,空格隔开。
1 2 3 4 5 6 7
| import sys for line in sys.stdin: a = line.split() ret = 0 for i in range(len(a)): ret += int(a[i]) print(ret)
|
输入为字符串
- 对输入的字符串进行排序后输出。
1 2 3 4 5 6 7 8
| while True: try: n = input() strList = list(map(str, input().split())) strList.sort() print(' '.joint(strList)) except: break
|
- 对输入的字符串进行排序后输出。多个测试用例,每个测试用例一行。每行用空格隔开,有n个字符。
1 2 3 4 5 6 7
| while True: try: arr = list(map(str, input().split())) arr.sort() print(' '.join(arr)) except: break
|
- 对输入的字符串进行排序后输出。多个测试用例,每个测试用例一行。每行通过,隔开,有n个字符。
1 2 3 4 5 6 7
| while True: try: a = input().split(",") a.sort() print(",".join(a)) except: break
|
其他问题
- 输入一个字符串,拆分成单个字符的列表。
1 2 3 4
| import sys str_input = sys.stdin.readline().split() strList = [i for i in str_input[0]] print(strList)
|
- 第一行表示接下来要输入几组数据
1 2 3 4
| count = list(map(int, input().split())) queue = [] for _ in range(count[0]): queue.append(list(map(int, input().split())))
|