笔试练习day16


感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接
🐒🐒🐒 个人主页
🥸🥸🥸 C语言
🐿️🐿️🐿️ C语言例题
🐣🐣🐣 python
🐓🐓🐓 数据结构C语言
🐔🐔🐔 C++
🐿️🐿️🐿️ 文章链接目录
🏀🏀🏀 笔试练习题
😎😎😎 实习日记
🐯🐯🐯 Git

字符串替换

字符串替换题目链接
在这里插入图片描述

题目解析

这道题简单的来说就是给你两个字符串,第一个字符串里面包含占位符%s,我们需要做的是将这个占位符用第二个字符串的字符替换掉,因为可能会出现占位符%s的个数小于第二个字符串字符的总个数,也就是说多出来的字符我们要追加到第一个字符串的末尾

代码


class StringFormat {
  public:
    string formatString(string A, int n, vector<char> arg, int m) {
        string::iterator a = A.begin();
        vector<char>::iterator b = arg.begin();
        while (a != A.end()) {
            if (*a == '%' && *(a + 1) == 's') {
                A.replace(a - A.begin(), 2, 1, *b);
                b++;
            }  a++;
        }
        while(b!=arg.end())
        {
            A.push_back(*b);
            b++;
        }
        return A;  
    }
};
代码解析

这道题如果我们要注意内存大小,一开始我用了三个变量a b s,s是string类型用来储存字符的,其实就是每次循环在s后面尾插一个a的字符,当遇到%s时就尾插b的字符,但是后面告诉我说内存超了,所以就没这样做,后面我又看了一下好像可以这样做,但是不知道哪写的不对,反正激素告诉我内存超了
之后就用的两个变量,但是做这道题的时候我发现我自己对string和vector的用法还是不熟,导致我知道要这么做,但是函数用的不对

因为题目中告诉的是保证参数个数大于等于占位符个数,所以我们不用怕b访问出界,因此第一个while循环我们不需要判断b,并且我们知道%s是两个字符,所以要判断a和a+1这两个字符是否是% 和 s,因为可能会出现只有一个%和只有一个s的情况
当满足条件时我们就替换这两个字符,最后一个while循环就是为了将b剩下的字符全部都尾插进a里面

下面是之前没改时的一个报错,这里的区别其实就是一个是a++,另一个是a+=2
也就是一个是满足条件就往后走两步,另一个是往后走一步,我们发现触发这个错误是因为两个%s是连在一起的,当我们替换掉一次后这个a所在的位置仍然是3,此时如果我们让a+=2后,我们发现他直接跳过了这个%s,所以我们需要改成a++
在这里插入图片描述

神奇数

神奇数题目链接
在这里插入图片描述

题目解析

这道题就是给你一个数,他有许多位,假设他的最高位为百位,此时我们需要从个位 十位 百位里面选择两个数出来组成一个新的数,如果这个数为质数那么就是神奇数,但是要注意组成后的最高位不是0,比如09,这样是不行的

这道题的解法是枚举+判断是否为质数
我们先将数以个位十位…一个一个的存进数组中,然后用两层for循环去枚举,(不需要注重顺序,我们只需要判断有没有神奇数就行了,存放的顺序不用关注)
在这里插入图片描述
在存的时候我们可以逆序存储,也可以把他以字符串的形式存储起来
在这里插入图片描述
这里我们选择第一种方法,我们规定i表示十位数,j表示各位数,用两次for循环的时候要注意i!=j,且i不能为0

之后就判断是否为质数,这个我们可以先求出他的平方根sqrt,然后再通过for循环从2到sqrt开始一个一个的除

代码

#include <iostream>
#include<cmath>
#include<vector>
using namespace std;
int a,b;
bool isprim(int n)
{
    if(n<2)return false;
    for(int i=2;i<=sqrt(n);i++)if(n%i==0)return false;
    return true;
}
int check(int n)
{
    vector<int>num;
    while(n)
    {
        num.push_back(n%10);
        n/=10;
    }
    for(int i=0;i<num.size();i++)
    {
        for(int j=0;j<num.size();j++)
        {
            if(i!=j&&num[i]!=0)
            {
                if(isprim(num[i]*10+num[j]))
                return 1;
            }
        }
    }
    return 0;
}
int main() {
    cin>>a>>b;
int ret=0;
for(int i=max(a,10);i<=b;i++)ret+=check(i);
        cout<<ret<<endl;
    }
代码解析

for(int i=max(a,10);i<=b;i++)中的int i=max(a,10)是为了保证我们判断的质数是两位数
if(i!=j&&num[i]!=0)这里是将i当成十位数的数字,所以num[i]不能为0,且i和j不能指向同一个数,num是一个vector构造的数组,我们通过push_back去逆序插入数字
isprim函数是判断是否为质数n%i==0就是不为质数的条件,所以返回false

HJ63 DNA序列

HJ63 DNA序列题目链接
在这里插入图片描述

题目解析

这道题有点难读懂
简单的说就是给了一个包含只有A C G T这几个字符的字符串,以及定义了一个GC-Ratio,他的含有就是G C这两个字母出现的总次数除以我们给定的子串长度,其中可能会出现两个子串的GC-Ratio相等的情况,此时以从左到右的顺序,输出最左边的子串

我们以题目的例子为例
ACGT,因为题目要求不能有AGT CT等这些情况,一开始我以为这里的等情况可能是AGTA 或者CTG…这种后面任意字母,结果我理解错了,其实这里说的就是出现的字符串必须是连续的,ACGT连续就是说字母顺序必须是按照A C G T这样的顺序,中间不可以缺少仍以一个字母,比如AGT缺少了C CT缺少了G

这道题我们可以用滑动窗口去做
以下面这个例子为例
在这里插入图片描述
我们可以定义两个指针left和right,然后right往后移动5个字母
在这里插入图片描述

之后统计这个窗口有多少个C G,统计完后如果用暴力解法的话left就会往后走一步,然后right再重新从left处开始走5步,重新统计
在这里插入图片描述
right其实可以不用这样重新倒回来再走的,我们只需要判断left和right指向的字母是否为C G
比如left在一开始就指向的C或G,那么往后走一步后就应该在之前的C G总数里减一,而如果right往后走一步后指向了C或G,那么就应该再加上一

所以就是我们需要用一个count去记录这个子串中C和G的总个数
在这里插入图片描述

代码

#include <iostream>
#include<string>
using namespace std;
string s;
int x;
int main() {
    cin >> s >> x;
    int begin = -1, maxCount = 0, count = 0, left = 0, right = 0, n = s.size();
    while (right < n) {
        if (s[right] == 'C' || s[right] == 'G')count++;
        while (right - left + 1 > x) {
            if (s[left] == 'C' || s[left] == 'G')count--;
            left++;
        }
        if (right - left + 1 == x) {
            if (count > maxCount) {
                begin = left;
                maxCount = count;
            }
        }
        right++;
    }
    cout << s.substr(begin, x) << endl;
    return 0;
}

代码解析

这里的x表示的是子串的长度,maxCount是记录最大的GC-Ratio,n表示的是输入的字符串的长度
第一个循环的条件要判断right是否超过字符串最大的长度

因为right是从最左边也就是字符串数组下标为0开始走的,所以他每走一步我们就要统计有多少个C和G

当right-left+1>x,则说明当前的长度已经是超过要求的子串长度了(因为数组下标是从0开始,假设我们规定的x为5,那么right应该走到4就停止,而left此时还在0位置,此时4-0的结果是不为5的,因此我们需要加1),此时需要让left往后走一步才能让子串长度为要求的长度,而要让left往后走那么就需要重新统计count的大小,如果s[left]为C G,如果是那么就count–

当长度为要求的子串长度的时候,我们要重新判断当前的C和G总数是否超过之前统计的C和G总数,如果超过的话就让maxCount=count,以及begin记录这个子串开始的位置

统计完后要让这个滑动窗口继续往后走,于是就让right++,当right++后就会重新出发 while (right - left + 1 > x)这个条件,此时left就会继续往后走,然后重新统计count

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值