3 条题解

  • 0
    @ 2025-12-5 21:40:26

    为什么这个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 以及你题目中的提示信息,问题出在查找的方向上。

    ❌ 错误原因分析

    1. 报错解读

      • Read 220:你的程序输出了下标 220
      • Expect 386:判题系统期望输出下标 386
      • 这说明数组中可能有重复的元素。目标值 t 既出现在下标 220 处,也出现在下标 386 处。
      • 你的代码是从前往后找(找到了 220 就停了),而题目要求的算法找到了后面的 386
    2. 关键提示解读

      • 题目提示中写道:“通过将需要查询的值与当前的元素值进行比较,不断向表头移动”。
      • 表头通常指数组下标 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
      @ 2025-12-5 21:22:05

      #检查错误

      #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*)。

      1. 原生数组没有 .size 成员变量
      2. 指针也无法知道数组原本有多长。

      修正方法:你需要把数组的长度 n 作为一个单独的参数传递给函数。

      ❌ 错误 2:返回值逻辑不完整

      你的 find 函数定义为 int 类型,必须保证所有路径都有返回值。

      1. 如果找到了,break 之后需要返回 i
      2. 如果循环结束都没找到(arr 遍历完了),函数末尾需要返回一个标识(通常是 -10)。

      ❌ 错误 3:缺少 main 函数上下文

      代码片段中后面读取 karr 的部分散落在函数外,这部分逻辑必须放在 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 结尾,你可以在整数数组的末尾放一个特殊值(比如 -10INT_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); 
      }
      

      🏆 总结建议

      1. 如果你是在刷题/考试:请使用 方法一(全局变量)。这是最省事、最不容易出错的方法。
      2. 如果你是在做工程开发:请老老实实传递长度,或者改用 vector。因为原生数组不传长度在工程中是巨大的安全隐患。
      • 0
        @ 2025-9-9 23:44:29

        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
        上传者