感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接
🐒🐒🐒 个人主页
🥸🥸🥸 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序列
题目解析
这道题有点难读懂
简单的说就是给了一个包含只有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