第一题
这个问题的算法倒是不难,但是存在一个小技巧,我们需要的是需要指定的字符,有些同学会写一堆if(条件a||条件b。。。),但是实际上题目只要求匹配字符,所以这些条件可以转化为设置一个需要匹配的字符数组,每次循环查找数组查看是否匹配对应的字符。
这样写好处有两个,一个是要写的东西少了,另一个是后续如果需要添加需要匹配的字符时,不需要修改if的代码,只需要修改要匹配的数组,从而减少了后续修改时产生误差的可能性(字符数组中添加一个错误的字符不影响之前的代码,但是if写错了可能编译就不通过了)
#include <iostream>
using namespace std;
int main(){
char target[]={'a','e','i','o','u','A','E','I','O','U'};
string s ;
getline(cin ,s);
int count = 0;
for(int i=0;i<s.size();i++)
{
for(int j=0;j<10;j++)
{
if(s[i] == target[j])
{
count++;
break;
}
}
}
cout <<"Count="<< count;
return 0;
}
第二题
这个题目很多同学想到了之前讲过的插入排序的方法,这很好,说明学到了一种解决问题的好办法。但是针对这题有一个更简答更快的办法
这种方法被称为计数排序,原理是将数据可能表示的范围作为辅助数组,如果原理数组中出现了某个元素,则将辅助数组中对应元素值的元素加一,换个说法可能比较容易理解
int a[10]; //元素值范围在0~100之间
int b[101];
for(int i=0;i<10;i++)
{
b[ a[i] ]++;
}
通过这种办法可以很快得出原来数组中有哪些元素,每个元素有多少个。
针对这题,ascii的范围不超过255,定义一个255长的辅助数组即可完成计算
#include <iostream>
using namespace std;
int main()
{
int count[255]={0};
string s ;
getline(cin, s);
for(int i=0;i<s.size();i++)
{
count[s[i]]++;
}
for(int i=254;i>-1;i--)
{
if(count[i] != 0)
{
cout << (char)i;
}
}
return 0;
}
第三题
这个题目就是很常见的字符串查找算法,同学们先尝试使用暴力匹配的思想去做即可。 假设现在我们面临这样一个问题:有一个文本串S,和一个模式串P,现在要查找P在S中的位置,怎么查找呢?
如果用暴力匹配的思路,并假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置,则有:
如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符;
如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0。相当于每次匹配失败时,i 回溯,j 被置为0。
至于KMP之类的优化算法同学们想看就看,这块自己动手推导一下就可以很快理解了字符串匹配算法,不想看也可以等后面数据结构那边再开始学习
#include <iostream>
using namespace std;
int main()
{
string s1,s2;
getline(cin, s1);
getline(cin, s2);
int max = s1.length()-s2.length();
int j = 0;
for(int i = 0;i < max;i++)
{
for(j = 0;j < s2.length(); j++)
{
if(s1[i + j] != s2[j])
break;
}
if(j == s2.length())
{
cout << i;
return 0;
}
}
cout <<-1;
return 0;
}
第四章
这题就是将之前的查找质数的方法进行封装,值得一提的是,这一题注重考查的是函数中很常见的边界输入情况分析,比如这一题,1也是有可能输入的数据,那1是不是质数呢,不是。所以就需要在原有的质数判断方法上做一个额外的判定
#include<iostream>
using namespace std;
bool isPrime(int n)
{
if(n == 1)
return false;
/** Begin **/
for(int i = 2; i * i <=n; i++)
{
if(n % i == 0)
{
return false;
}
}
return true;
/** End **/
}
int main()
{
int m, n;
cin >> m >> n;
/** Begin **/
int count = 0;
for(int i = m;i <= n; i++)
{
if (isPrime(i))
count++;
}
cout << count;
/** End **/
return 0;
}
第五题
这个题目主要是检查一下同学们对于字符串输入的理解情况,一开始输入一个字符串这一步应该是没有问题,问题在于将字符串取出来,一步步来就可以了
- 首先将首尾的
[]
去除,得到"str1","str2"......
这种字符串,通过substr实现 - 接下来找到并记录第一个逗号
,
,从而知道第一个带引号的的字符串的整体的下标,这一步通过简单计算就能得到不带引号的字符串改用什么下标 - 接下来重复寻找并记录逗号的过程,利用当前找到的逗号和上一个逗号之间的信息就可以依次截取出对应的字符串,当然,对于最后一个逗号,既然知道它是最后一个逗号,那么它后面就是最后一个字符串,这一步也就顺理成章出来了
#include <iostream>
#include<string>
using namespace std;
//找到两个字符串之间最长公共前缀的长度
int compare(string s1, string s2)
{
int ret=-1;
int target =min(s1.size(),s2.size());
for(int i=0;i<target;i++)
{
if(s1[i]==s2[i])
ret++;
}
return ret;
}
int main()
{
string str;
cin >>str;
str = str.substr(1, str.size()-2);
int minLen=0;
string strs[10]={""};
int wordIndex=0;
int current=str.find(',');
int lastStart = -1;//上一个逗号的下标
while(current != string::npos)
{
//比较一下两个逗号之间的字符个数和我们需要截取的字符个数就可以得知要截取多长的字符串
strs[wordIndex] = str.substr(lastStart + 2, current - lastStart - 3);
minLen = min(minLen, (int)strs[wordIndex++].size());
lastStart = current;
current = str.find(',', current + 1);
}
//最后一个单词没有考虑进去,需要加上
strs[wordIndex++] = str.substr(lastStart + 2,str.size() - lastStart - 3);
int sameIndex=0;
string currentStr=strs[0];
for(int i = 1; i<wordIndex;i++)
{
sameIndex = compare(strs[i],currentStr);
currentStr = currentStr.substr(0,sameIndex + 1);
}
cout << '"'<<currentStr<<'"';
}