历年CSP-J初赛真题解析 | 2023年CSP-J初赛完善程序(33-42)

学习C++从娃娃抓起!记录下CSP-J备考学习过程中的题目,记录每一个瞬间。

附上汇总贴:历年CSP-J初赛真题解析 | 汇总_csp真题题解-CSDN博客


#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;
}

33、①处应填( )

A.1

B.nums[0]

C.right

D.left

【答案】:B

【解析】

第9行可以判断出代码为二分搜索,所以第11行和第13行肯定是left和right两个指针的移动,故第10行应该是判断满足什么条件时,left指针需要移动。mid左侧为连续的数字时,left需要移动。num[mid]= mid+num[0]时,左侧数字是连续的,选B。

可以代入nums = [1,2,3,5,6]进行验算,第一次while循环,mid = 2,nums[2] == 3,满足nums[mid] == mid + num[0](3 == 2 + 1)。

34、②处应填( )

A.left = mid + 1

B.right = mid - 1

C.right = mid

D.left = mid

【答案】:A

【解析】

mid左侧数据满足连续时,left指针需要移到mid的右侧,所以A选项left = mid+1满足。

35、③处应填( )

A.left = mid + 1

B.right = mid - 1

C.right = mid

D.left = mid

【答案】:C

【解析】

mid左侧数据不连续,则右侧数据肯定连续。因此需要把right指针改为mid,下一轮从mid的左侧区域开始查找。所以选C

36、④处应填( )

A.left + nums[0]

B.right + nums[0]

C.mid + nums[0]

D.right + 1

【答案】:A

【解析】

当退出while循环时,一定是left指针指向那个被移除的数前面一个数,用left+nums[0]就可以得到被移除的数,所以选A。

37、⑤处应填( )

A.nums[0] + n

B.nums[0] + n - 1

C.nums[0] + n + 1

D.nums[n-1]

【答案】:D

【解析】

题目描述中提到“除非被移除的是第一个或最后一个元素”,所以要打印“Sequence is consecutive”,只可能移除第一个或最后一个元素,4个选项D为最后一个元素,所以选D

(编辑距离)给定两个字符串, 每次操作可以选择删除(Delete)、插入(Insert)、替换(Replace),一个字符, 求将第一个字符串转换为第二个字符串所需要的最少操作次数。

试补全动态规划算法。

#include <iostream>
#include <string>
#include <vector>
using namespace std;

int min(int x, int y, int z) {
    return min(min(x, y), z);  //三个整数求最小值
}

int edit_dist_dp(string str1, string str2) {
    int m = str1.length();  //str1的长度
    int n = str2.length();  //str2的长度
    vector<vector<int>> dp(m + 1, vector<int>(n + 1));  //创建一个二维数组dp

    for (int i = 0; i <= m; i++) {
        for (int j = 0; j <= n; j++) {
            if (i == 0)
                dp[i][j] = ①;
            else if (j == 0)
                dp[i][j] = ②;
            else if (③)
                dp[i][j] = ④;
            else
                dp[i][j] = 1 + min(dp[i][j - 1], dp[i - 1][j], ⑤);
        }
    }
    return dp[m][n];
}

int main() {
    string str1, str2;
    cin >> str1 >> str2;
    cout << "Minimum number of operations: "
         << edit_dist_dp(str1, str2) << endl;
    return 0;
}

38、①处应填( )

A.j

B.i

C.m

D.n

【答案】:A

【解析】

dp[m][n]表示长度为m的字符串变成长度为n的字符串最少步数,那么dp[0][j]就应该表示str1长度为0的字符串变成长度为j的字符串最少步数。显然应该是添加j个字符,所以选A

39、②处应填( )

A.j

B.i

C.m

D.n

【答案】:B

【解析】

同39题,dp[m][n]表示长度为m的字符串变成长度为n的字符串最少步数,那么dp[i][0]就应该表示str1长度为i的字符串变成长度为0的字符串最少步数。显然应该是删除i个字符,所以选B

40、③处应填( )

A.str1[i - 1] == str2[j - 1]

B.str1[i] == str2[j]

C.str1[i - 1] != str2[j - 1]

D.stri[i] != str2[j]

【答案】:A

【解析】

因为第24行应该是判断str1和str2某个位置字符不相等时的处理,故这里就应该是字符相等的位置。str1和str2的第i个字符应该是str1[i-1],选A

41、④处应填( )

A.dp[i - 1][j - 1] + 1

B.dp[i - 1][j - 1]

C.dp[i - 1][j]

D.dp[i][j - 1]

【答案】:B

【解析】

这里是动态规划的基本概念,如果两个字符相等,str1的i字符变成str2的j个字符最少步数,就等于str的i-1个字符变成str2的j-1个字符的最少步数。选B

42、⑤处应填( )

A.dp[i][j] + 1

B.dp[i - 1][j - 1] + 1

C.dp[i - 1][j - 1]

D.dp[i][j]

【答案】:C

【解析】

3个数字应该分别对应着插入、删除和替换。插入的话,就是相当于i比j多1,dp[i][j-1]就对应着插入。删除的话,就是相当于i比j少1,dp[i-1][j]就对应着删除。替换的话,i和j的数量相等,C选项满足要求。

5个空选出来后,可以带入abc和abd字符进行验算。打表如下:

i  0 1 2 3 
j 0 0 1 2 3
  1 1 0 1 2 
  2 2 1 0 1
  3 3 2 1 1
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值