目录
- 1.字符串最后一个单词
- 2.计算字符个数
- 3.排序与去重
- 4.字符串分割
- 5.进制转换
- 6.质数因子
- 7.取近似值
- 8.合并表记录
- 9.提取不重复的整数
- 10.字符个数统计
- 11.数字颠倒
- 12.字符串反转
- 13.句子逆序
- 14.字符串的连接最长路径查找
- 15.求int型正整数在内存中存储时1的个数
- 16.购物单
- 17.坐标移动
- 18.密码验证合格程序
- 19.删除字符串中出现次数最少的字符
- 20.字符串排序–非字母数字顺序不变
- 21.查找兄弟单词
- 22.字符串加解密
- 23.简单密码
- 24.字符串合并处理
- 25.回文字符串
- 26.字符串加密
- 27.统计每个月兔子的总数
- 28.求小球落地5此后所经历的路程和第五次反弹的高度
- 29.统计字符串中不同类别字符的个数
- 30.按字节截取字符串
- 31.数组中重复的数字
1.字符串最后一个单词
计算并输出字符串最后一个单词的长度
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char str[5001];
//输入字符串
gets(str); // cin不接受空格、tab键的输入
//计算并输出字符串最后一个单词的长度
cout << str << endl;
int len =0;
for(int i = strlen(str) - 1; str[i] != ' ' && i >= 0; i--)
len++;
cout << len << endl;
return 0;
}
2.计算字符个数
写出一个程序,接受一个由字母和数字组成的字符串,和一个字符,然后输出字符串中含有该字符的个数;不区分大小写
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char str[100];
char ch;
// 输入一个由字母和数字组成的字符串
cin >> str;
cin >> ch;
cout << "str = " << str << '\n' << "ch = " << ch << endl;
// 输出输入字符串中含有该字符的个数
int count = 0;
// int i = 0;
// while(str[i] != '\0')
// {
// if(str[i] == ch || str[i] == ch + 32 || str[i] == ch - 32)
// count++;
// i++;
// }
for(int i = 0; str[i] != '\0'; i++)
{
if(str[i] == ch || str[i] == ch + 32 || str[i] == ch - 32)
count++;
}
cout << count << endl;
return 0;
}
3.排序与去重
用计算机生成了N个1到1000之间的随机整数(N<=1000),对于其中重复的数字,只保留一个,把其余的相同的数去掉;然后再把这些数从小到大排序,请完成以上问题中的“去重”和“排序”工作
测试样例1: 3个数字, 分别是2,2,1
测试样例2:11个数字,分别是10,20,40,32,67,40,20,89,300,400,15
#include <iostream>
using namespace std;
int main()
{
int num, n;
while(cin >> num)
{
int a[1001]={0}; //hash表思路,复杂度为o(n)
while(num--)
{
cin >> n;
a[n] = 1;
}
for(int i = 1; i < 1001; i++)
if(a[i] == 1)
cout << i << endl;
}
return 0;
}
注意:该题采用了哈希表思路,定义的数组必须初始化,否则内存中之前存入数据将会参与运算,否运行将会出错。
4.字符串分割
连续输入字符串,请按长度为8拆分每个字符串后输出到新的字符串数组;长度不是8整数倍的字符串请在后面补数字0,空字符串不处理
输入 abc 123456789 输出 abc00000 12345678 900000000
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
while(getline(cin, str))
{
//循环 截取前八个,
while(str.size() > 8)
{
cout << str.substr(0, 8) << endl; //获得字符串从第0位开始长度为8的字符串
str = str.substr(8); //获得字符串从第8位开始到尾的字符串
}
cout << str.append(8 - str.size(), '0') << endl;
}
return 0;
}
length()与size()没有区别,都是返回string对象中元素数量,即返回std::distance(begin(),end()) 。length是因为沿用C语言的习惯而保留下来的,string类最初只有length,引入STL之后,为了兼容又加入了size,它是作为STL容器的属性存在的,便于符合STL的接口规则,以便用于STL的算法。
str.substr()函数
- 形式:str.substr(pos, n)
- 解释:返回一个string,包含s中从pos开始的n个字符的拷贝(pos的默认值是0,n的默认值是s.size() - pos,即不加参数会默认拷贝整个s)
- 补充:若pos的值超过了string的大小,则substr函数会抛出一个out_of_range异常;若pos+n的值超过了string的大小,则substr会调整n的值,只拷贝到string的末尾
str.append()函数
append函数是向string的后面追加字符或字符串。
-
向string的后面加C-string
string s = “hello “; const char *c = “out here “;
s.append©; // 把c类型字符串s连接到当前字符串结尾
s = “hello out here”; -
向string的后面加C-string的一部分
string s=”hello “;const char *c = “out here “;
s.append(c,3); // 把c类型字符串s的前n个字符连接到当前字符串结尾
s = “hello out”;
3).向string的后面加string
string s1 = “hello “; string s2 = “wide “; string s3 = “world “;
s1.append(s2); s1 += s3; //把字符串s连接到当前字符串的结尾
s1 = “hello wide “; s1 = “hello wide world “; -
向string的后面加string的一部分
string s1 = “hello “, s2 = “wide world “;
s1.append(s2, 5, 5); 把字符串s2中从5开始的5个字符连接到当前字符串的结尾
s1 = “hello world”;
string str1 = “hello “, str2 = “wide world “;
str1.append(str2.begin()+5, str2.end()); //把s2的迭代器begin()+5和end()之间的部分连接到当前字符串的结尾
str1 = “hello world”; -
向string后面加多个字符
string s1 = “hello “;
s1.append(4,’!’); //在当前字符串结尾添加4个字符!
s1 = “hello !!!”;
————————————————
转载原文链接:https://blog.csdn.net/wxn704414736/article/details/78551886
5.进制转换
写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。(多组同时输入)
输入0xA ,输出 10
#include <iostream>
using namespace std;
int main()
{
string str;
while(getline(cin, str))
{
if(str.size() < 0)
break;
int num = 0;
for(int i =2; i < str.size(); i++)
{
if(str[i] >= '0' && str[i] <= '9')
num = num * 16 + str[i] - '0';
else
num = num * 16 + str[i] - 'A' + 10;
}
cout << num << endl;
}
return 0;
}
6.质数因子
输入一个long型正整数,按照从小到大的顺序输出它的所有质因子(如180的质因子为2 2 3 3 5),最后一个数后面也要有空格
#include <iostream>
using namespace std;
int main()
{
long num;
while(cin >> num)
{
//for循环从小到大的质数因子
for(int i = 2; i * i < num; i++) // 使用i^2 < num 比i <= num时间复杂度低
{
while(num % i == 0)
{
cout << i << ' ';
num /= i;
}
}
//数字本身就是质数
if(num > 1)
cout << num << ' ';
}
return 0;
}
7.取近似值
写出一个程序,接受一个正浮点数值,输出该数值的近似整数值
验证:输入5.5 输出6
#include <iostream>
using namespace std;
int main()
{
double num; //一般情况下不用float,因为float强转会产生很多问题
cin >> num;
int a = (int)num; //强转
if((num - a) * 10 >= 5)
cout << a + 1 << endl;
else if((num - a) * 10 <= -5)
cout << a - 1 << endl;
else
cout << a << endl;
return 0;
}
8.合并表记录
数据表记录包含包含表索引和数值(int范围的整数),请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算,输出按照key值升序进行输出
输入描述:先输入键值对的个数,然后输入成对的index和value值,以空格隔开
输出描述:输出合并后的键值对(多行)
示例:
输入:4
0 1;0 2; 1 2;3 4
输出:0 3;1 2;3 4
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int num; //键值对数
cin >> num;
unordered_map<int, int> hash;
vector<int> key_map;
while(num--)
{
int key, value;
cin >> key >> value;
key_map.push_back(key); //有重复的
hash[key] += value;
}
//去重
sort(key_map.begin(), key_map.end());
key_map.erase(unique(key_map.begin(), key_map.end()), key_map.end());
//遍历打印
for(vector<int>::iterator iter = key_map.begin(); iter != key_map.end(); ++iter)
cout << *iter << " " << hash[*iter] << endl;
return 0;
}
unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。
unorder_map库详细介绍
vector库详细介绍
sort函数详细介绍
unique函数详细介绍
9.提取不重复的整数
输入一个intx型整数,按照从右向左的阅读顺序,返回一个不含重复数字的新的整数
验证:输入 9876673 输出37689
/** 9.提取不重复的整数 */
#include <iostream>
#include <unordered_map>
using namespace std;
int main()
{
unordered_map<int, int> hash;
int num;
int out = 0;
cin >> num;
while(num)
{
if(hash[num % 10] == 0)
{
hash[num % 10]++;
out = out * 10 + num % 10;
}
num /= 10;
}
cout << out << endl;
return 0;
}
10.字符个数统计
编写一个函数,计算字符串中含有的不同字符的个数。字符在ASCII码范围内(0~127),换行表示结束符,不在范围内的不作统计
验证:输入 abc 输出 3
采用数组方法
#include <iostream>
using namespace std;
int main()
{
char ch[500];
int arr[128] = {0};
int count = 0;
gets(ch);
for(int i = 0; ch[i] != '\0'; i++)
{
arr[ch[i]]++;
}
for(int k = 0; k < 128; k++)
{
if(arr[k] > 0)
count++;
}
cout << count << endl;
return 0;
}
采用hash表
#include <iostream>
#include <unordered_map>
using namespace std;
int main()
{
int sum = 0;
unordered_map<char, int> hash;
char ch[500];
cin >> ch;
for(int i = 0; ch[i] != '\0'; i++)
{
if(ch[i] >= 0 && ch[i] <= 127)
hash[ch[i]] = 1;
}
for(int k = 0; k < hash.size(); k++)
{
if(hash[k] == 1)
sum++;
}
cout << sum <<endl;
}
11.数字颠倒
输入一个int型整数,将这个整数以字符串的形式逆序输出;
程序不考虑负数的情况,若数字含有0,则逆序形式也含有0,如输入为100,则输出为001。
验证:输入 1516000 输出 0006151
/** 第11题: 数字颠倒 */
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
int num;
cin >> num;
while(num != 0)
{
char ch = num % 10 + '0';
num /= 10;
str += ch;
}
cout << str << endl;
return 0;
}
关于不引用库,C++11版本之后也能使用 string str,因为std标准库包含了string库,故编译器不会报错;
但是隐式包含不代表真正的引用,因此为了程序的稳定可靠还是应该显式引用
12.字符串反转
写出一个程序,接受一个字符串,然后输出该字符串反转后的字符串,(字符串长度不超过1000)
验证:输入 abcd 输出 dcba
方法一:反向遍历显示
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
cin >>str;
for(int i = str.length() - 1; i >= 0; i--)
cout << str[i];
return 0;
}
方法二:使用reverse函数
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
string str;
getline(cin, str);
reverse(str.begin(),str.end());
cout << str << endl;
return 0;
}
13.句子逆序
将一个英文语句以单词为单位逆序排放,得到一个逆序的句子。
验证:输入 I am a boy 输出 boy a am I
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string str;
getline(cin, str);
//翻转句子中所有字符
reverse(str.begin(), str.end());
//翻转单个单词
for(int i = 0; i < str.size(); i++)
{
//定位单个单词的首尾
int j = i;
while(j < str.size() && str[j] != ' ')
j++;
reverse(str.begin() + i, str.begin() + j);
i = j;
}
cout <<str << endl;
return 0;
}
换个方法
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
getline(cin, str);
int pos = 0;
for(int i = str.length(); i >= 0; i--)
{
pos++;
if(str[i] == ' ')
{
cout << str.substr(i + 1, pos - 1) << ' ';
pos = 0;
}
}
cout << str.substr(0, pos) << endl;
return 0;
}
-
gets函数
所在头文件:cstdio
gets(ch + begin);
功能:读取字符串存储在ch数组中(第一位存在ch[begin]),直至接受到换行符或EOF时停止,并将读取的结果存放在buffer指针所指向的字符数组中。换行符不作为读取串的内容,读取的换行符被转换为‘\0’空字符,并由此来结束字符串。
返回值:读入成功,返回与参数buffer相同的指针;读入过程中遇到EOF(End-of-File)或发生错误,返回NULL指针。所以在遇到返回值为NULL的情况,要用ferror或feof函数检查是发生错误还是遇到EOF。
-
参数:
char类型数组的首地址(不可以是string类型的)
-
-
getline函数
所在头文件:iostream
getline(cin, str, ch);
功能:读取字符串存储在str字符串中(第一位存在ch[begin])。如果有第三个参数直至接受到ch或EOF时停止,否则默认第三个参数为换行符。读取的ch被转换为‘\0’空字符,并由此来结束字符串。
返回值:读入成功时返回读取的字节数,失败返回-1。
-
参数:
读入方式(大部分情况下都为cin) 必要
string类型的字符串 必要
char类型的字符 选要
-
-
注意:
gets与getline的本质区别是gets是读入char类型字符数组的,而getline是读入string类型的字符串的。而且getline函数还可以读到你指定的字符结束,而gets只能读到换行符结束。
14.字符串的连接最长路径查找
题目描述:给定n个字符串,请对n个字符串按照字典序排列。
输入描述:输入第一行为一个正整数n( 1 ≤ n ≤ 1000 1\leq n \leq1000 1≤n≤1000),下面n行为n个字符串(字符串长度 ≤ 100 \leq100 ≤100),字符串中只含有大小写字母。
输出描述:数据输出n行,输出结果为按照字典排序的字符串。
验证:
输入:
9
cap
to
cat
card
two
too
up
boat
boot
输出:
boat
boot
cap
card
cat
to
too
two
up
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
bool cmp(const string &str1, const string &str2);
int main()
{
int n;
cin >> n;
vector<string> vec; //定义一个容器用来存放字符数串
while(n--)
{
string str;
cin >> str;
vec.push_back(str);
}
sort(vec.begin(), vec.end(), cmp);
for(auto x : vec) cout << x << endl;
return 0;
}
bool cmp(const string &str1, const string &str2)
{
return str1 < str2;
}
注意:自定义函数bool cmp()函数中,对变量str1, str2都是引用,为防止原变量被修改,应使用const修饰
15.求int型正整数在内存中存储时1的个数
题目描述:输入一个int型的正整数,计算出该int型数据在内存中存储时1的个数。
输入描述:输入一个整数(int类型)
输出描述:这个数转换成2进制后,输出1的个数
验证: 输入5 输出2
#include <iostream>
using namespace std;
int main()
{
int num;
cin >> num;
int count = 0;
while(num)
{
if(num & 1) //与1相“与”
count++;
num = num >> 1;
}
cout << count << endl;
return 0;
}
16.购物单
题目描述:
公司发了N元的年终奖,xx决定把年终奖用于购物,想买的物品分为两类:主件与附件,附件是从属于某个主件的。
下表就是一些主件与附件的例子:
主件 | 附件 |
---|---|
电脑 | 打印机、扫描仪 |
书柜 | 图书 |
书桌 | 台灯、文具 |
工作椅 | 无 |
如果要买归类为附件的物品,必须先买该附件所属的主件,每个主件可以有0个、1个或2个附件,附件不再有从属于自己的附件。
想买的东西很多,为了不超出预算,把每件物品规定了一个重要度,分为5等:用整数1 ~ 5表示,第5等最重要。
从因特网上查到了每件物品的价格(都是10元的整数倍),并且希望在不超过N元(可以等于N元)的前提下,使每件物品的价格与重要度的乘积的综合最大,设第
j
j
j件物品的价格为
V
[
j
]
V[j]
V[j],重要度为
W
[
j
]
W[j]
W[j],共选中
k
k
k件物品,编号依次为
j
1
,
j
2
,
…
,
j
k
j_1, j_2, \dots, j_k
j1,j2,…,jk,则所求的总和为:
V
[
j
1
]
∗
W
[
j
1
]
+
V
[
j
2
]
∗
W
[
j
2
]
+
⋯
+
V
[
j
k
]
∗
W
[
j
k
]
V[j_1]*W[j_1]+V[j_2]*W[j_2]+\dots+V[j_k]*W[j_k]
V[j1]∗W[j1]+V[j2]∗W[j2]+⋯+V[jk]∗W[jk]。
请你帮助王强设计一个满足要求的购物单。
输入描述:
输入的第1行,为两个正整数,用一个空格隔开:N m(其中N < 32000,表示总钱数;m < 60 ,为希望购买物品的个数);
从第2行到第m+1行,第 j j j行给出了编号为 j − 1 j-1 j−1的物品的基本数据,每行有3个非负整数 v p q(其中 v < 10000,表示该物品的价格;p 表示物品的重要度,取值1 ~ 5之间;q 表示该物品是主件还是附件,q = 0表示物品为主件,q > 0表示物品为附件,q 是所属主件的编号)
输出描述:
输出文件只有一个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值(< 200000)
示例
输入:
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0
输出:2200
- 该问题为动态路径规划问题,详细分析参考博客
#include <iostream>
#include <vector>
using namespace std;
int dp[3200]; //总钱数 < 32000/10,价格为10的整数倍
int main()
{
int N; //预算的总钱数
int m; //物品的个数
cin >> N >> m;
//定义数组,主件价格,主件 价格*重要度,附件1价格,附件2价格,附件1 价格*重要度,附件2 价格*重要度
vector<int> master(m + 1), master_vw(m + 1), annex1(m + 1), annex2(m + 1), annex1_vw(m + 1), annex2_vw(m + 1);
for(int i = 1; i <= m; i++)
{
int v, p, q; //v 价格, p 重要度, q表示附件有无,进一步表示附件编号
v = v / 10; //价格为10的整数倍
cin >> v >> p >> q;
//主件
if(q == 0)
{
master[i] = v; //保留主件价格
master_vw[i] = v * p; //保留主件 价格*重要度
}
//附件1
else if(annex1[q] == 0)
{
annex1[q] = v;
annex1_vw[q] = v * p;
}
else if(annex2[0] == 0)
{
annex2[q] = v;
annex2_vw[q] = v * p;
}
}
//动态规划
for(int i = 1; i <= m; i++)
{
for(int j = N; j >= 1; j--)
{
//只买主件
if(j >= master[i])
dp[j] = max(dp[j], dp[j - master[i]] + master_vw[i]);
//主件+附件1
if(j >= master[i] + annex1[i])
dp[j] = max(dp[j], dp[j - master[i] - annex1[i]] + master_vw[i] + annex1_vw[i]);
//主件+附件2
if(j >= master[i] + annex2[i])
dp[j] = max(dp[j], dp[j - master[i] - annex2[i]] + master_vw[i] + annex2_vw[i]);
//主件+附件1+附件2
if(j >= master[i] + annex1[i] + annex2[i])
dp[j] = max(dp[j], dp[j - master[i] - annex1[i] - annex2[i]] + master_vw[i] + annex1_vw[i] + annex2_vw[i]);
}
}
cout << dp[N] << endl;
return 0;
}
17.坐标移动
题目描述:
开发一个坐标计算工具,A表示向左移动,D表示向右移动,W表示向上移动,S表示向下移动。从(0,0)点开始移动,从输入字符串里面读取一些坐标,并将最终输入结果输出到输出文件里面。
输入:
合法坐标为A(或者D或者W或者S)+ 数字(两位以内),坐标之间以;间隔。
非法坐标点需要进行丢弃。如AA10; A1A;YAD;等
示例:
输入:A10; S20; W10; D30; X; A1A; B10A11; ; A10
处理过程:起点(0,0)+ A10 = (-10,0) + S20 = (-10, -20) + W10 = (-10,-10) + D30 = (20, -10) + D30 = (20, -10) + X(无效) + A1A(无效) + B10A11(无效) + 空(不影响) + A10 = (10,-10)
输出:10,-10
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string str;
while(cin >> str)
{
//初始化坐标
int x = 0, y = 0;
vector<string> steps; //存储单步操作
//把字符串拆分为单步操作 A10 S20
int wordlen = 0;
for(int i = 0; i < str.size(); i++)
{
while(str[i] != ';')
{
wordlen++;
i++;
}
steps.push_back(str.substr(i - wordlen, wordlen));
wordlen = 0;
}
for(auto x : steps) cout << x << endl; //查看是否分解成功
cout << "初始坐标:" << x << ',' << y << endl;
//对单个step执行坐标变换
for(int i = 0; i < steps.size(); i++)
{
int num = 0; //坐标移动数值
if(steps[i].length() == 3 && steps[i][1] >= '0' && steps[i][1] <= '9' && steps[i][2] >= '0' && steps[i][2] <= '9') //长度为3的坐标 A10
num = (steps[i][1] - '0') * 10 + steps[i][2] - '0'; //将字符转为整型数字
else if(steps[i].length() == 2 && steps[i][1] >= '0' && steps[i][1] <= '9') //长度为2的坐标 A5
num = steps[i][1] - '0'; //将字符转为整型数字 */
else continue;
switch(steps[i][0]) //ASDW
{
case 'A': x -= num;
break;
case 'D': x += num;
break;
case 'W': y += num;
break;
case 'S': y -= num;
break;
default: break;
}
cout << "当前坐标:" << x << ',' << y << endl;
}
cout << "变换后坐标:" << x << ',' << y << endl;
}
return 0;
}
18.密码验证合格程序
题目描述:
1.长度超过8位
2.包括大小写字母、数字、其他符号,以上四种至少三种
3.不能有相同长度超2的子串重复
/** 密码验证程序 */
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
vector<string> res; // OK, NG
string str;
while(cin >> str)
{
//1.长度超过8位
if( str.size() <= 8 )
res.push_back( "NG" );
else
{
//2.包括大小写字母、数字、其他符号,以上四种至少三种
int num[4] = { 0 }; //存放包含类型字符的判断
for( auto it = str.begin(); it != str.end(); it++ )
{
if( (*it) >= 'A' && (*it) <= 'Z' )
num[0] = 1;
else if( (*it) >= 'a' && (*it) <= 'z' )
num[1] = 1;
else if( (*it) >= '0' && (*it) <= '9' )
num[2] = 1;
else
num[3] = 1;
}
int count = 0;
for( int i = 0; i < 4; i++ )
count += num[i];
if(count < 3)
res.push_back( "NG" );
else
{
//3.不能有相同长度超2的子串重复
string::size_type pos;//size_t pos
for(int i = 0; i < str.size(); i++)
{
string sub = str.substr(i, 3);
pos = str.find(sub, i + 3);
if(pos != string::npos) // 匹配了
break;
}
if(pos == string::npos) // 没匹配
res.push_back("OK");
else
res.push_back("NG");
}
}
for(auto x : res)
cout << x << endl;
res.clear();
}
return 0;
}
补充:
string中find()返回值是字母在母串中的位置(下标记录),如果没有找到,那么会返回一个特别的标记npos。(返回值可以看成是一个int型的数)
19.删除字符串中出现次数最少的字符
题目描述
实现删除字符串中出现次数最少的字符,若多个字符出现次数一样,则都删除。输出删除这些单词后的字符串,字符串中其它字符保持原来的顺序。
如果文件有多组输入,多个字符串用回车隔开。
**输入描述:**
字符串只包含小写英文字母,不考虑非法输入,输入的字符串长度小于等于20个字节。
**输出描述:**
删除字符串中出现次数最少的字符后的字符串。
/** 19.删除字符串中出现次数最少的字符 */
#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>
using namespace std;
int main()
{
string str;
int minnum;
unordered_map<char, int> hash; //定义一个hash表
while(cin >> str)
{
for(int i = 0; i < str.size(); i++)
hash[str[i]]++; //初始化hash表
minnum = hash[str[0]];
// 对比找到最小的
for(int i = 1; i < str.size(); i++)
minnum = min(minnum, hash[str[i]]);
for(int i = 0; i < str.size(); i++)
{
if(hash[str[i]] > minnum)
cout << str[i];
}
cout << endl;
}
return 0;
}
20.字符串排序–非字母数字顺序不变
题目描述:
编写一个程序,将输入字符串中的字符按如下规则排序。
- 英文字母从A到Z排列,不区分大小写。
- 同一个英文字母的大小写同时存在时,按照输入顺序排列。
- 非英文字母的其它字符保持原来的位置。
输入 :About Nothing (2012/8)
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string str;
vector<char> alp; // 字母顺序存储
while(getline(cin, str))
{
for(int i = 0; i < 26; i++)
for(int j = 0; j < str.size(); j++)
if(str[j] - 'a' == i || str[j] - 'A' == i)
alp.push_back(str[j]);
for(int k = 0, n = 0; k < str.size() && n < alp.size(); k++)
if(str[k] >= 'a' && str[k] <= 'z' || str[k] >= 'A' && str[k] <= 'Z')
str[k] = alp[n++];
cout << str << endl;
alp.clear();
}
return 0;
}
21.查找兄弟单词
题目描述
兄弟单词:给定一个单词,如果通过任意交换单词中字母的位置得到不同的单词Y,那么定义Y是X的兄弟单词。(bca是abc的兄弟单词;abc与abc是相同单词,不是兄弟单词)
单词:由小写字母组成,不含其他字符。
字典顺序:两个单词(字母按照自左向右顺序),先以第一个字母作为排序的基准,如果第一个字母相同,就用第二个字母为基准,如果第二个字母相同就以第三个字母为基准。依次类推,如果到某个字母不相同,字母顺序在前的那个单词顺序在前。如果短单词是长单词从首字母开始连续的一部分,短单词顺序在前。
示例:
先输入字典中单词的个数,再输入n个单词作为字典单词。再输入一个单词,查找其在字典中兄弟单词的个数,再输入数字n(要兄弟单词的位置)。输出查找到的兄弟单词的个数。
输入:3 abc bca cab abc 1
输出:2 , bca
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n; // 字典中单词个数
while(cin >> n)
{
vector<string> dic; // 字典
string word;
// 字典初始化
for(int i = 0; i < n; i++)
{
cin >> word;
dic.push_back(word);
}
string target; // 目标单词
cin >> target;
// 处理 搜索兄弟单词
vector<string> res; // 记录所有兄弟单词
string temp = target; // 临时变量
sort(temp.begin(), temp.end()); // 排序
int lent = target.size(); // 目标单词的长度
for(int i = 0; i < n; i++)
{
int lenDic = dic[i].size();
if( (lenDic == lent) && (target!= dic[i]) ) //长度一致 单词不同
{
string tempDic = dic[i];
sort(tempDic.begin(), tempDic.end());
if(temp == tempDic)
res.push_back(dic[i]);
}
}
int index; // res[index - 1]
cin >> index;
if(index > res.size() && index < 1)
{
cout << "\n输入错误,重新输入:";
cin >> index;
}
cin >> index;
// 坑 一定要字典排序
sort(res.begin(), res.end());
cout << res.size() << endl;
cout << res[index - 1] << endl;
dic.clear();
res.clear();
}
return 0;
}
22.字符串加解密
题目描述:
1.对输入的字符串进行加解密,并输出。
2.加密方法:当内容是英文字母时则用该英文字母的后一个字母替换,同时字母变换大小写,如字母a时则替换为B;字母Z时则替换为a;
当内容是数字时则把该数字加1,如0替换1,1替换2,9替换0;
其他字符不作变化。
3.解密方法为加密的逆过程。
接口描述:实现接口每个接口实现一个基本操作:
void Encrypt(char aucPassword[], char aucResult[]):在函数中实现字符串加密并输出
int unEncrypt(char result[], char password[]):在该函数中实现字符串解密并输出
说明:1.字符串以\0结尾。2.字符串最长100个字符。
#include
#include
using namespace std;
// 利用对比方式解决问题
string data1 = “abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789”;
string data2 = “BCDEFGHIJKLMNOPQRSTUVWXYZAbcdefghijklmnopqrstuvwxyza1234567890”;
int main()
{
string str1,str2;
while(cin >> str1 >> str2)
{
for(int i = 0; i < str1.size(); i++)
str1[i] = data2[data1.find(str1[i])];
for(int i = 0; i < str2.size(); i++)
str2[i] = data1[data2.find(str2[i])];
cout << str1 << "\n" << str2 << endl;
}
return 0;
}
23.简单密码
题目描述:
加密方法:手机上的字母:1 - 1, abc - 2, def - 3, ghi - 4, jkl - 5, mno - 6, pqrs - 7, tuv - 8, wxyz - 9, 0 - 0,把密码中出现的小写字母都变成对应的数字,数字和其他的符号都不做变换。
声明:密码中没有空格,而密码中出现的大写字母则变成小写之后一位往后移动一位,如:X,先变成小写,再往后移动一位,变为y。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
while(cin >> str)
{
// 加密,小写字母变数字
// 1 - 1, abc - 2, def - 3, ghi - 4, jkl - 5, mno - 6, pqrs - 7, tuv - 8, wxyz - 9, 0 - 0
for(int i = 0; i < str.size(); i++)
{
if(str[i] >= 'a' && str[i] <= 'c')
str[i] = '2';
if(str[i] >= 'd' && str[i] <= 'f')
str[i] = '3';
if(str[i] >= 'g' && str[i] <= 'i')
str[i] = '4';
if(str[i] >= 'j' && str[i] <= 'l')
str[i] = '5';
if(str[i] >= 'm' && str[i] <= 'o')
str[i] = '6';
if(str[i] >= 'p' && str[i] <= 's')
str[i] = '7';
if(str[i] >= 't' && str[i] <= 'v')
str[i] = '8';
if(str[i] >= 'w' && str[i] <= 'z')
str[i] = '9';
if(str[i] >= 'A' && str[i] < 'Z')
str[i] += 33; // 等价于str[i]+=' '+1;
if(str[i] == 'Z')
str[i] = 'a';
}
cout << str << endl;
}
return 0;
}
24.字符串合并处理
题目描述:
将输入的字符串合并,对合并后的字符串进行排序。要求:下标为奇数的字符和下标为偶数的字符分别从小到大排序。(下标指字符在字符串中的位置)
对排序后的字符串进行操作,如果字符为‘0’——‘9’或‘A’——‘F’或者‘a’——‘f’,则对他们所代表的16进制的数进行BIT倒序操作,并转换为相应的大写字符。如字符为‘4’,为0100b,则翻转后为0010b,转换后的字符为‘2’;如字符为‘7’,为0111b,则翻转后为1110b,转换后的字符为大写‘E’。
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
const string helper1 = "0123456789abcdefABCDEF";
const string helper2 = "084C2A6E195D3B7F5D3B7F";
int main()
{
string str1, str2, mergestr;
string strOdd, strEven;
while(cin >> str1 >> str2)
{
mergestr = str1 + str2;
// 奇数偶数分开
for(int i = 0; i < mergestr.size(); i++)
{
if(i % 2 == 1)
strOdd += mergestr[i];
else
strEven += mergestr[i];
}
// 奇数偶数排序
sort(strOdd.begin(), strOdd.end());
sort(strEven.begin(), strEven.end());
// 重新合并
for(int i = 0; i < mergestr.size(); i++)
{
if(i % 2 == 0)
mergestr[i] = strEven[i / 2];
else
mergestr[i] = strOdd[i / 2];
}
for(int i = 0; i < mergestr.size(); i++)
{
int index = helper1.find(mergestr[i]);
if(index != -1)
mergestr[i] = helper2[index];
}
cout << mergestr << endl;
}
return 0;
}
## 24.单词倒排
**题目描述:**
对字符串中的所有单词进行倒排。要求如下:
1.每个单词是以26个大写或小写英文字母构成;
2.非构成单词的字符均视为单词间隔符;
3.要求倒排后的单词间隔符以一个空格表示;如果原字符串中相邻单词间有多个间隔符倒排转换后也只允许出现一个空格间隔符;
4.每个单词最长20个字母;
```cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string str;
while(getline(cin, str))
{
vector<string> word;
string temp = "";
for(int i = 0; i < str.size(); i++)
{
if(str[i] >= 'a' && str[i] <= 'z' || str[i] >= 'A' && str[i] <= 'Z')
temp += str[i];
else
{
if(temp.size() > 0)
{
word.push_back(temp);
temp = "";
}
}
}
// 最后一个单词没有读入
if(temp.size() > 0)
word.push_back(temp);
// 倒序输出word
for(int i = word.size() - 1; i > 0; i--)
cout << word[i] << ' ';
cout << word[0] << endl;
}
return 0;
}
25.回文字符串
返回字符串中回文串的最大长度。
输入:ABBA
输出:4
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
while(cin >> s)
{
int maxlen = 0;
int n = s.size();
for(int i = 1; i < n; i++)
{
// 奇数 ABA
int low = i - 1, high = i + 1;
while(low >= 0 && high < n && s[low] == s[high])
low --, high ++;
if(high - low - 1 > maxlen)
maxlen = high - low - 1;
// 偶数 ABBA
low = i -1, high = i;
while(low >= 0 && high < n && s[low] == s[high])
low --, high ++;
if(high - low - 1 > maxlen)
maxlen = high -low - 1;
}
cout << maxlen << endl;
}
return 0;
}
改进代码:
ABA 变为 #A#B#A# (7 / 2 = 3)
ABBA 变为 #A#B#B#A# (9 / 2 = 4)
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
while(cin >> s)
{
int maxlen = 0;
// ABA 变为 #A#B#A# (7 / 2 = 3)
// ABBA 变为 #A#B#B#A# (9 / 2 = 4)*
// 扩充字符串
string temp = "#";
for(int i = 0; i < s.size(); i++)
{
temp.append(1, s[i]);
temp.append(1, '#');
}
s = temp;
int n = s.size();
for(int i = 1; i < n; i++)
{
// 奇数 ABA
int low = i - 1, high = i + 1;
while(low >= 0 && high < n && s[low] == s[high])
low --, high ++;
if(high - low - 1 > maxlen)
maxlen = high - low - 1;
}
cout << maxlen / 2 << endl;
}
return 0;
}
26.字符串加密
题目描述:
有一种技巧可以对数据进行加密,器原理是:选择一个单词作为密钥,如TRAILBLAZERS。如果单词中包含有重复的字母,只保留第一个,其余几个丢弃,然后用字母表中剩余的字母填充完整。
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
T R A I L B Z E S C D F G H J K M N O P Q U V W X Y
上面的一行作为明文,下面一行是密钥加密之后的密文。
示例:
输入:nihao, ni
输出:le
#include <iostream>
#include <string>
using namespace std;
int main()
{
string key, s;
while(cin >> key >> s)
{
// 创建加密表
string alp;
int arr[26] = {0}; // /hash表记录对应26个字母
for(int i = 0; i < key.size(); i++)
{
// 小写字母
if(key[i] >= 'a' && key[i] <= 'z')
{
if( arr[key[i] - 'a'] == 0 )
{
arr[key[i] - 'a'] = 1;
alp += key[i] - 32; // 统一大写
}
}
// 大写字母
if(key[i] >= 'A' && key[i] <= 'Z')
{
if( arr[key[i] - 'A'] == 0 )
{
arr[key[i] - 'A'] = 1;
alp += key[i] - 32; // 统一大写
}
}
}
// 填充加密表
for(int i = 0; i < 26; i++)
if(arr[i] == 0)
alp += 'A' + i;
// 查表输出
for(int i = 0; i < s.size(); i++)
{
if(s[i] >= 'a' && s[i] <= 'z')
cout << char(alp[s[i] - 'a'] + ' ');
if(s[i] >= 'A' && s[i] <= 'Z')
cout << char(alp[s[i] - 'A']);
}
cout << endl;
}
return 0;
}
27.统计每个月兔子的总数
题目描述:
有一只兔子,从出生后第3个月起每个月都生一只兔子,小兔子长到第三个月后每个月又生一只兔子,加入兔子不死,问每个月兔子总数为多少?
示例:
输入: 9
输出:34
#include <iostream>
using namespace std;
int main()
{
int month;
while(cin >> month)
{
int first = 1, second = 0, third = 0; // first 出生1个月的兔子总数, second 出生2个月的兔子总数,third出生三个月的兔子总数
while(--month)
{
third += second; // 三个月的兔子 = 原来三个月的 + 当前两个月的
second = first; // 两个月的兔子 = 原来一个月的
first = third; // 新生一个月的兔子 = 现在三个月的
}
cout << first + second + third << endl;
}
return 0;
}
28.求小球落地5此后所经历的路程和第五次反弹的高度
题目描述:
假设一个球从任意高度自由落下,每次落地后反跳回原高度的一半再落下,求在它第五次落地时,共经历多少米?第5次反弹多高?
精度范围是小数点6位
示例:
输入:1
输出:2.875, 0.03125
#include <iostream>
using namespace std;
int main()
{
int high;
while(cin >> high)
{
double sum = high;
double height = high;
for(int i = 1; i < 5; i++)
{
height /= 2.0;
sum += height * 2;
}
cout << sum << '\n' << height / 2 << endl;
}
return 0;
}
29.统计字符串中不同类别字符的个数
题目描述:
输入一行字符,分别统计出包含英文字母、空格、数字和其它字符的个数。
输入:输入一行字符串,可以有空格
输出:英文字符、空格字符、数字字符、其他字符的个数
#include <iostream>
using namespace std;
int main()
{
string s;
while(getline(cin, s))
{
int cnt1 = 0, cnt2 = 0, cnt3 = 0, cnt4 = 0;
for(int i = 0; i < s.size(); i++)
{
if((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z'))
cnt1++;
else if( s[i] == ' ' )
cnt2++;
else if( s[i] >= '0' && s[i] <= '9')
cnt3++;
else
cnt4++;
}
cout << cnt1 << '\n' << cnt2 << '\n' << cnt3 << '\n' << cnt4 << endl;
}
return 0;
}
30.按字节截取字符串
题目描述:
编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取字符串,但是要保证汉字不被介半个,如“我ABC”4,应该截为“我AB”,输入“我ABC汉DEF”6,应该输出为“我ABC”而不是“我ABC+汉的半个”。
#include <iostream>
using namespace std;
int main()
{
string str;
int num;
while(cin >> str >> num)
{
// string自带截取
// cout << str.substr(0, num) << endl;
// 汉字在ASCII码中是负数 小于0
int temp = num - 1;
while(temp >= 0 && str[temp] < 0)
temp--;
if( (num - temp) % 2 == 0 )
num--;
cout << str.substr(0, num) << endl;
}
return 0;
}
31.数组中重复的数字
在一个长度为 n 的数组里的所有数字都在 0 到 n - 1 的范围内。数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复几次。
请找出数组中任意一个重复的数字。例如,如果输入长度为 7 的数组{2, 3, 1, 0, 2, 5, 3},那么对应的输出是第一个重复的数字2。
改变数组中元素位置
#include <iostream>
using namespace std;
class Solution
{
public:
bool duplicate(int numbers[], int length, int* duplication)
{
for(int i = 1; i < length; i++)
{
while(numbers[i] != i)
{
if(numbers[i] == numbers[ numbers[i] ])
{
duplication[0] = numbers[i];
return true;
}
else
swap(numbers[i], numbers[ numbers[i] ]);
}
}
return false;
}
};
int main()
{
int length = 7;
int numbers[] = { 2, 3, 1, 0, 2, 5, 3 };
int duplication[] = { 0 };
Solution solution;
solution.duplicate(numbers, length, duplication);
cout << duplication[0] << endl;
return 0;
}