CSP-J 2023 入门级 第一轮 完善程序(1)

【题目】

CSP-J 2023 入门级 第一轮 完善程序(1)
(1)(寻找被移除的元素)问题:原有长度为n+1、公差为1的等差升序数列;将数列输入到程序的数组时移除了一个元素,导致长度为n的升序数组可能不再连续,除非被移除的是第一个或最后一个元素。需要在数组不连续时,找出被移除的元素。
试补全程序。

#include <iostream>
#include <vector>
using namespace std;
int find_missing(vector<int>& nums) {
    int left = 0, right = nums.size() - 1;
    while (left < right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == mid +) {} else {}
    }
    return}

int main() {
    int n;
    cin >> n;
    vector<int> nums(n);
    for(int i = 0; i < n; i++)cin >> nums[i];
    int missing_number = find_missing(nums);
    if (missing_number ==) {
        cout << "Sequence is consecutive" << endl;
    } else {
        cout << "Missing number is " << missing_number << endl;
    }
    return 0;
}
  1. ①处应该填( )
    A. 1 B. nums[0] C. right D. left
  2. ②处应该填( )
    A. left = mid + 1 B. right = mid – 1
    C. right = mid D. left = mid
  3. ③处应该填( )
    A. left = mid + 1 B. right = mid – 1
    C. right = mid D. left = mid
  4. ④处应该填( )
    A. left + nums[0] B. right + nums[0]
    C. mid + nums[0] D. right + 1
  5. ⑤处应该填( )
    A. nums[0]+n B. nums[0]+n-1 C. nums[0]+n+1 D. nums[n-1]

【题目考点】

1. 二分查找

【解题思路】

先看主函数

int main() {
    int n;
    cin >> n;
    vector<int> nums(n);
    for(int i = 0; i < n; i++)cin >> nums[i];
    int missing_number = find_missing(nums);
    if (missing_number ==) {
        cout << "Sequence is consecutive" << endl;
    } else {
        cout << "Missing number is " << missing_number << endl;
    }
    return 0;
}

输入n,输入n个元素保存在顺序表nums中,下标0~n-1。根据题目,等差数列公差为1,一共n+1个数字,如果被移除的不是nums[0],那么这n+1个数字最小值为nums[0],最大值应该为nums[0]+n,在这n+1个数中移除一个数字。
调用find_missing函数,查找丢失的数字,赋值给missing_number。
如果丢失的数字是(5),那么输出“序列是连续的”,否则输出丢失的数字。
也就是说如果丢失的数字是n+1个数字中的第1个或最后一个,find_missing函数会返回(5)处应该填的值,此时整个序列就是连续的。

int find_missing(vector<int>& nums) {
    int left = 0, right = nums.size() - 1;
    while (left < right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == mid +) {} else {}
     }
     return}

而后看find_missing函数,传入是的nums的引用。看这一代码结构,有left, right, mid,自然是使用了二分查找算法。
设为nums的元素下标从0~nums.size()-1,先将left, right指向nums保存的序列的两端。
只要left < right,每次循环取中点位置mid为mid = left+(right-left)/2,该写法在数学意义上等价于mid = (left+right)/2

之所以写成mid = left+(right-left)/2,是因为这个写法可以保证即使left+right的值超过int可以表示的数值范围,仍能正确求出(left+right)/2的值

在整数域二分查找算法中,如果取中点的写法为mid = (left+right)/2,那么就是在求满足某一条件的最小值的最小下标。(反之,如果取中点的写法为mid = (left+right+1)/2,那么就是在求满足某一条件的最大值的最大下标。)
该题要找的是缺失的数字,那么二分查找的条件就可以是“大于缺失数字”,二分查找后找到的是“大于缺失数字的最小值的最小下标”。
二分查找的过程中,要始终保持要寻找的值的下标在left~right范围之内。

  • 如果mid满足条件“大于缺失数字”,则看看有没有满足条件的更小的数字,取左半边,mid满足条件应该保留在left~right范围之内,所以应该让right = mid
  • 如果mid不满足条件“大于缺失数字”,则应该找更大的数字让其满足条件,取右半边,mid不满足条件应该在left~right范围之外,所以应该让left = mid+1

设数字序列起始值为s,去掉的数字为s+m。

012m-1mm+1n-1n
原数字序列ss+1s+2s+m-1s+ms+m+1s+n-1s+n
去掉m后的序列:numsss+1s+2s+m-1s+m+1s+m+2s+n

可以看到,在下标小于m的范围内,nums[i]的值应该等于s+i,下标大于等于m时,nums[i]的值应该等于s+i-1
假设去掉的数字不是第一个数字s,起始数字s就是nums[0]nums[mid]应该与mid+nums[0]比较,(1)处应该填nums[0],选B。

  • 如果nums[mid]的值是mid+nums[0],那么mid一定小于缺失的数字,不满足条件“大于缺失数字”,应该让left = mid+1,(2)处选A。
  • 如果nums[mid]的值不是mid+nums[0],那么mid一定大于缺失的数字,满足条件“大于缺失数字”,应该让right = mid,(3)处选C。

while循环跳出后,left或right的值就是找到的是"大于缺失数字"的最小值的最小下标,该下标就是上表中的m,缺失的值应该是s+m,也就是代码中的nums[0]+leftnums[0]+right,(4)处选A或B。

如果去掉的数字就是第一个数字s,或最后一个数字,整个序列是连续的序列,无论mid为何值,都满足nums[mid]==mid+nums[0],按照上述写法运行程序,会不断的改变left,而right不变,直到while循环跳出,此时left与right的值都为right的初始值nums.size()-1,返回值应该为nums[0]+nums.size()-1
在主函数中,nums的长度nums.size()就是n,因此当整个序列是连续序列时,find_missing函数的返回值missing_number就是nums[0]+n-1,由于序列连续公差为1,nums[0]+n-1就是nums[n-1]
而当缺失的数字是大于nums[n-2],小于nums[n-1]的数字时,求大于缺失数字的最小值的最小下标,得到的结果(while循环跳出后left或right的值)也是n-1,find_missing函数返回的值也是nums[0]+n-1,此时nums[0]+n-1不为nums[n-1]
所以只有返回的nums[0]+n-1的值与nums[n-1]的值相等时,序列才是连续的。
(5)处选D。

【答案】

  1. B
  2. A
  3. C
  4. A或B
  5. D
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
2023 csp-j入门级第一轮试题是中国计算机科学会议(CSP)针对初学者设计的一道题。根据题目的具体要求,试题内容可能涉及算法、编程语言、数据结构等方面的知识。 对于这样的试题,学生们需要运用自己所学的知识和技能,通过编程实现题目要求。例如,可能需要设计一个算法来解决一个具体的问题,或者使用特定的数据结构来组织和处理数据。 为了完成这样的试题,学生们首先需要理解题目的要求和限制条件,确保对题目中涉及的概念和术语有所了解。接下来,他们需要分析问题,确定解决问题的方法和步骤。在实际编程实现时,可以选择合适的编程语言和工具,并按照题目要求进行编码。 在完成编码后,学生们需要进行测试和调试,确保程序能够正确运行并得到正确的结果。在测试过程中,可以使用一些已知的测试用例来验证程序的正确性,并对程序进行优化,以提高其性能。 最后,将代码提交,并等待评审结果。评审过程可能涉及代码质量、算法复杂度、正确性等方面的考量。根据评审结果,学生们可以了解自己的编程水平和不足之处,并进行相应的学习和提高。 总体来说,解答2023 csp-j入门级第一轮试题需要学生在编程基础上运用算法和数据结构的知识,进行问题的分析和解决。通过这样的学习和实践,学生们可以提高自己的编程能力,并逐渐成长为优秀的程序员。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值