科大讯飞20230715笔试算法

声明:里面的算法是自己思考得来,没有进行网判。思路不对,代码错误还请指正。

第一题:小y删数字

给定一个长度为n的数组,数组元素为a1, a2, . . , an,每次能删除任意a的任意一位,求将所有数字变成0最少需要几步。 例如103若删除第1位则变成3;若删除第2位则变成13;若删除第3位则变成10。 输入描述 第一行一个正整数n代表数组长度。接下来一行n个数第j个数代表a。

1≤n ≤10^5 0≤ai≤10^9

输出描述

输出一行一个数代表答案。 示例1 输入

5
10 13 22 100 30
输出

7
思路与代码
统计不是0的数位个数。

#include<iostream>
#include<vector>

using namespace std;

int main(){
    int n;
    cin>>n;
    int ans = 0;
    for(int i=0;i<n;i++){
        int x = 0;
        cin>>x;
        while (x)
        {
            if(x%10) ans++;
            x = x/10;
        }
    }
    cout<<ans<<endl;
    return 0;
}

第二题:小红的字符串切割

小红拿到了一个字符串,她希望你帮她切割成若干子串,满足以下两个条件:

子串长度均为不小于3的奇数。

子串内部的字符全部相同。

输入描述

第一行输入一个正整数n,代表字符串长度。第二行输入一个字符串,仅由小写字母组成。1 <n ≤200000 输出描述 如果无解,请输出-1。 否则按顺序输出若干个字符串,用空格隔开。

示例1

输入

8
aaabbbbb
输出

aaa bbbbb
思路与代码
将其分成块为3的,因此最后只能剩0,1,2这3种情况,因此再往前吸收,而发现只有余1的时候往前吸收两次,注意特判。

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

int main(){

    int n = 0;
    cin>>n;
    vector<vector<int> > ans;
    std::string temp;
    cin>>temp;
    for(int i=0;i<temp.size();){
        int right = i+1;
        while (right<temp.size()and temp[right] == temp[i])
        {
            right++;
        }
        if(right-i<3) {
            cout<<-1;
            return 0;
        }
        if (right-i == 4)
        {
            cout<<-1;
            return 0;
        }
        
        // 如果是偶数需要拆分
        if(((right-i)&1) == 0){
            // 需要拆分成两个大于3的奇数
            int j = i;
            for(;j+3<=right;j++){
                ans.push_back(vector<int>{j, j+3});
            }
            ans[ans.size()-1][1]+=right-j;
            if((ans[ans.size()-1][1]-ans[ans.size()-1][0]&1) == 0){
                // 就要往后吸收了
                int index = ans.size()-2;
                ans[index][1] = ans[ans.size()-1][1];
                ans.pop_back();
            }
        }else{
            ans.push_back(vector<int>{i, right});
        }
        i = right;
    }
    // 最后根据然后输出
    for(auto&it:ans){
        cout<<temp.substr(it[0], it[1]-it[0])<<" ";
    }
    cout<<endl;
    return 0;
}

第三题:小红的数字匹配

定义一个“模板串”为一个由数字字符和′?"组成的字符串。我们可以通过将问号替换成数字字符来得到正整数。显然,一个模板串可能会和多个正整数匹配。例如: “1?2"可以和102或者132等正整数匹配。请注意,匹配的正整数不能包含前导零,例如”??1"可以匹配101,但不能匹配001。 小红拿到了一个模板串,她想知道,和这个模板串匹配的正整数中,第k小的是多少?

输入描述

第一行输入一个正整数t,代表询问次数。接下来的2* t行,每两行为一次询问: 第一行输入一个字符串,仅由数字字符和?'组成。第二行输入一个正整数k,代表询问的是第k小。

1≤t ≤ 10^4 1≤k≤10 ^9

字符串长度不超过30。

输出描述

输出t行,每行输出一个答案。 如果一共都没有k个匹配的正整数,则输出-1。否则输出第小的匹配的正整数。

示例1

输入

4
??1
1
22?
100000000
2??
3
000???
1
输出

101
-1
202
-1
思路与代码
此题就这样思考比如
看例子:??8??k=3。那么我们匹配得来的最小的数字是8所在数位定了,其他位置要么是1-9,要么是0-9,因此,可以直接把8位去掉,得。4位?,然后注意?的数字范围,得到这四位数字的最小值和最大值,然后网上加k-1,如果超过最大值直接返回-1,否则得到的结果就是对应?号的数位结果,位置复原,就是最终的结果。
比如上述例子:
最小值是数位拿出来1000。加上3-1=2得1002 。8位复原10802。就是最终的结果。

#include<iostream>
#include<string>

using namespace std;

int main(){
    int n = 0;
    int k = 0;
    cin>>n;
    while (n--){
        string temp;
        cin>>temp;
        if(temp[0] == '0'){
            cout<<-1<<endl;
            continue;
        }
        cin>>k;
        int bits = 0;
        
        for(int i=0;i<temp.size();i++){
            if(temp[i] == '?') bits++;
        }
        int bits2 = bits;
        int lower = 0;
        int hight = 0;
        if (temp[0] == '?')
        {
            lower = pow(10, bits-1);
            hight = 9;
            bits--;
            while(bits--){
                hight = hight*10+9;
            }
        }else{
            lower = 0;
            hight = 9;
            bits--;
            while(bits--){
                hight = hight*10+9;
            }
        }
        if(lower+k > hight){
            cout<<-1<<endl;
            continue;
        }else{
            lower+=k-1;
        }
        std::string cur = to_string(lower);
        std::string cur_ = "";
        cur_.append(bits2-cur.size(),'0');
        cur_.append(cur);
        int index = 0;
        std::string ans = "";
        for(int i=0;i<temp.size();i++){
            if(temp[i] == '?'){
                ans.push_back(cur_[index++]);
            }else{
                ans.push_back(temp[i]);
            }
        }
        cout<< ans<<endl;
    }
    return 0;
}

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值