3 条题解
-
0
为什么这个WA?
Wrong Answer 0On line 1: Read 220, expect 386.
#include <bits/stdc++.h> using namespace std; int find(int arr[],int n,int t){ int i=-1; for(i=0;i<n;i++){ if(arr[i]==t){ return i;//找到直接break 或者直接return i } } return -1; } int main(){ int n,k; cin>>n>>k; int arr[510]; for(int i=0;i<n;i++){ cin>>arr[i]; } for(int i=0;i<k;i++){ int t; cin>>t; cout<<find(arr,n,t)<<" "; } }这是一个非常典型的 OJ 判题错误反馈。根据报错信息
Read 220, expect 386以及你题目中的提示信息,问题出在查找的方向上。❌ 错误原因分析
-
报错解读:
Read 220:你的程序输出了下标220。Expect 386:判题系统期望输出下标386。- 这说明数组中可能有重复的元素。目标值
t既出现在下标220处,也出现在下标386处。 - 你的代码是从前往后找(找到了
220就停了),而题目要求的算法找到了后面的386。
-
关键提示解读:
- 题目提示中写道:“通过将需要查询的值与当前的元素值进行比较,不断向表头移动”。
- 表头通常指数组下标
0的方向。 - “向表头移动”意味着查找的起点应该是表尾(数组末尾),然后依次向前遍历。
结论:这道题强制要求使用从后往前(倒序)的顺序查找。
✅ 修正后的代码
你需要将
find函数中的循环改为从n-1开始递减到0。#include <bits/stdc++.h> using namespace std; // 查找函数 int find(int arr[], int n, int t) { // 【修改点】题目提示"向表头移动",说明要从后往前找 // 这样如果数据有重复,就会返回下标最大的那个(或者题目逻辑本身就是倒序扫描) for(int i = n - 1; i >= 0; i--) { if(arr[i] == t) { return i; } } return -1; // 没找到 } int main() { // 优化输入输出 ios::sync_with_stdio(false); cin.tie(0); int n, k; if (!(cin >> n >> k)) return 0; int arr[510]; for(int i = 0; i < n; i++) { cin >> arr[i]; } for(int i = 0; i < k; i++) { int t; cin >> t; cout << find(arr, n, t) << " "; } // 补上题目要求的行尾换行 cout << endl; return 0; }💡 为什么之前是 220 而答案是 386?
假设数组是
[..., 5, ..., 5, ...]。- 第一个
5在下标220。 - 第二个
5在下标386。 - 正序查找(
i++):遇到220就返回了。 - 倒序查找(
i--):从末尾回来,先遇到386就返回了。
修改为倒序循环后,你应该就能通过这个测试点了!
-
-
0
#检查错误
#include <bits/stdc++.h> using namespace std; int find(int arr[],int t){ int i=-1; for(i=0;i<arr.size;i++){ if(arr[i]==t){ break;//找到直接break 或者直接return i } } … for(int i=0;i<k;i++){ int t; cin>>t; cout<<find(arr,t)<<" "; } }这段代码主要有 三个核心错误,其中最严重的是关于函数声明的传参时数组长度的处理。
以下是详细的错误分析和修改方案:
❌ 错误 1:
arr.size是无效语法在 C++ 中,当你把一个原生数组(如
int arr[])作为参数传递给函数时,它会退化成一个指针(int*)。- 原生数组没有
.size成员变量。 - 指针也无法知道数组原本有多长。
修正方法:你需要把数组的长度
n作为一个单独的参数传递给函数。❌ 错误 2:返回值逻辑不完整
你的
find函数定义为int类型,必须保证所有路径都有返回值。- 如果找到了,
break之后需要返回i。 - 如果循环结束都没找到(
arr遍历完了),函数末尾需要返回一个标识(通常是-1或0)。
❌ 错误 3:缺少
main函数上下文代码片段中后面读取
k和arr的部分散落在函数外,这部分逻辑必须放在main函数里。
✅ 修改方案一:使用原生数组(最符合你现在的代码风格)
我们需要在
find函数中增加一个参数n来表示数组长度。#include <bits/stdc++.h> using namespace std; // 修改点 1: 增加 int n 参数接收数组长度 int find(int arr[], int n, int t) { // 建议:直接在循环里 return,比 break 更简洁 for (int i = 0; i < n; i++) { if (arr[i] == t) { return i + 1; // 假设返回 1-based 下标(如果是 0-based 就返回 i) } } return -1; // 修改点 2: 找不到时返回 -1 } int main() { int n, k; // 假设 n 是数组长度,k 是查询次数 cin >> n; // 输入数组长度 int arr[10005]; // 定义一个足够大的数组 for(int i = 0; i < n; i++) { cin >> arr[i]; } cin >> k; // 输入查询次数 for (int i = 0; i < k; i++) { int t; cin >> t; // 修改点 3: 调用时传入长度 n cout << find(arr, n, t) << " "; } return 0; }
✅ 修改方案二:使用
vector(更现代的 C++ 写法)如果你想使用
.size(),应该使用std::vector容器替代原生数组。注意vector的 size 是方法,需要加括号.size()。#include <bits/stdc++.h> using namespace std; // 修改点 1: 参数改为 vector<int>& (引用传递更快) int find(vector<int>& arr, int t) { // 修改点 2: vector 有 .size() 方法,注意要加括号 () for (int i = 0; i < arr.size(); i++) { if (arr[i] == t) { return i + 1; // 返回下标(根据题目要求决定是否+1) } } return -1; // 没找到 } int main() { int n, k; cin >> n; vector<int> arr(n); // 定义 vector for(int i = 0; i < n; i++) { cin >> arr[i]; } cin >> k; for (int i = 0; i < k; i++) { int t; cin >> t; cout << find(arr, t) << " "; // 这里不需要传 n 了 } return 0; }总结
- 原生数组 (
int[]):必须手动传递长度n。 vector:可以使用.size(),但记得加括号()。- 返回值:确保找不到元素时也有
return语句(通常是-1)。
如果用原生数组又不想传递长度的话有办法吗?
严格来说,在 C++ 中,原生数组一旦作为参数传递给函数,就会退化成指针,函数内部彻底丢失长度信息,这是语言特性。
但是,如果你非要**“不传递长度参数”**,有以下 3 种“歪门邪道”(变通方法),在不同场景下可以使用:
方法一:使用全局变量(OI/刷题最常用 🔥)
这是在信息学奥赛(OI)和刷题中最常见的做法。既然不想传参,那就把数组和长度定义在所有函数外面,大家都能直接看到。
- 优点:函数定义简洁,不需要传参。
- 缺点:全局变量占用静态内存(但刷题时这通常是好事,防止爆栈)。
#include <bits/stdc++.h> using namespace std; // 【重点】把数组和 n 定义在 main 外面 int arr[10005]; int n; int find(int t) { // 这里的 n 和 arr 直接读取全局变量 for (int i = 0; i < n; i++) { if (arr[i] == t) { return i + 1; } } return -1; } int main() { int k; cin >> n; // 读取到全局变量 n for(int i = 0; i < n; i++) cin >> arr[i]; cin >> k; for (int i = 0; i < k; i++) { int t; cin >> t; cout << find(t) << " "; // 【重点】不需要传 arr 和 n 了 } return 0; }
方法二:设置“哨兵”结尾(C语言风格)
类似于 C 语言字符串以
\0结尾,你可以在整数数组的末尾放一个特殊值(比如-1、0或INT_MAX),前提是这个值绝不会出现在正常的有效数据中。- 优点:不需要传递长度。
- 缺点:如果有效数据里包含了你的哨兵值,逻辑就崩了。
#include <bits/stdc++.h> using namespace std; // 假设输入的数据都是正数,我们可以用 -1 作为结束标记 int find(int arr[], int t) { int i = 0; // 【重点】循环条件改为:只要不是哨兵(-1)就继续 while (arr[i] != -1) { if (arr[i] == t) return i + 1; i++; } return -1; } int main() { int n, arr[10005]; cin >> n; for(int i = 0; i < n; i++) cin >> arr[i]; // 【重点】手动在有效数据后面加个哨兵 arr[n] = -1; int t; cin >> t; cout << find(arr, t); // 只传数组,不传长度 }
方法三:使用 C++ 模板推导(高级写法)
如果你定义的数组是固定大小的(例如
int arr[100]),可以使用模板引用来保留数组长度信息。- 优点:保留了数组长度,无需手动传参。
- 致命缺点:模板推导的是数组的总容量(Capacity),而不是你实际填入的元素个数(Size)。比如你开了
arr[1000]但只输入了5个数,模板会告诉你长度是1000,导致你可能会遍历到后面 995 个垃圾值。
#include <bits/stdc++.h> using namespace std; // 模板参数 N 会自动捕获数组的大小 template<size_t N> int find(int (&arr)[N], int t) { // 注意:这里的 N 是数组的总容量(例如 100),不是输入的 n // 如果你不介意遍历整个数组(包括后面没赋值的 0),可以用这个 for (int i = 0; i < N; i++) { if (arr[i] == t) return i + 1; } return -1; } int main() { // 必须是编译期确定大小的数组 int arr[10] = {1, 3, 5, 7, 9}; // 剩下 5 个自动补 0 // 可以直接传,模板自动推导出 N=10 cout << find(arr, 5); }🏆 总结建议
- 如果你是在刷题/考试:请使用 方法一(全局变量)。这是最省事、最不容易出错的方法。
- 如果你是在做工程开发:请老老实实传递长度,或者改用
vector。因为原生数组不传长度在工程中是巨大的安全隐患。
- 原生数组没有
-
0
C :
#include <stdio.h> int main(){ int n,tmp,i,m,a[500]; // freopen("1.txt","r",stdin); while (scanf("%d %d",&n,&m)!=EOF) { for (i=0;i<n;i++) { scanf("%d",&a[i]); } while (m--) { scanf("%d",&tmp); for (i=n-1;i>=0;i--) { if (tmp==a[i]) { printf("%d ",i); break; } } if (i==-1) { printf("-1 "); } } printf("\n"); } // fclose(stdin); return 0; }C++ :
#include <cstdio> #include <cstdlib> #include <stack> #include <algorithm> using namespace std; const int MAXN = 500; int val[MAXN + 1]; int main() { int n, k, position, query; scanf("%d%d", &n, &k); for (int i = 0;i < n;i++) { scanf("%d", &val[i + 1]); } for (int i = 0;i < k;i++) { scanf("%d", &query); val[0] = query; position = n; while (val[position] != query) position--; printf("%d ", position - 1); } puts(""); return 0; }
- 1
信息
- ID
- 373
- 时间
- 1000ms
- 内存
- 32MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 1
- 上传者