题目一
给定一个数组arr,求差值为k的去重数字对。
思路
对于数组中的每个值,使用STL里面的find查找是否有与之差值为k的值存在,如果存在,则在用于标记的数组mark中将该数字的索引位置标为1.最后将每个索引位置被标为1的值存入set容器中进行去重。
实现代码
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
using namespace std;
set<int> remove(vector<int>&nums, int k){
vector<int>mark(nums.size());
//找到相应的数字,记录数字的索引位置
for(int i=0;i<nums.size();i++){
if((find(nums.begin(), nums.end(),nums[i]-k)!=nums.end())||
(find(nums.begin(), nums.end(),nums[i]+k)!=nums.end())){
mark[i]=1;
}
}
//放到set里面,自动去重
set<int>answer;
for(int i=0; i<nums.size(); i++){
if(mark[i])
answer.insert(nums[i]);
}
return answer;
}
int main(){
vector<int>nums={3,16,53,72,33,1,6,7,3,73,146,23,64,1,78,52};
int k=13;
set<int>answer=remove(nums, k);
for(auto i : answer)
cout<<i<<endl;
return 0;
}
加题
如果两个只包含小写英文字母的字符串所含字符种类相同,则这两个字符串被称为同源词。比如“ab”和“abbba”就是同源词。“ab”和“abbbbc”就不是同源词。
写一个函数,判断两个词是否为同源词
思路
还是用set。分别村两个字符串的各个字符。如果两个set容器的size相同,则两个词是同源词。(这个太简单,就不实现了)
或者使用26位二进制代表一个词,每一位对应一个字母。如果两个字符串对应的数相同,则说明两个词是同源词。
实现代码:
#include<iostream>
using namespace std;
void compare(string first, string second){
int num1=0, num2=0;
for(int i=0; i<first.length(); i++){
num1 |= 1<<(first[i]-'a');
}
for(int j=0; j<second.length(); j++){
num2 |=1<<(second[j]-'a');
}
if(num1==num2)
cout<<"两个字符串同源"<<endl;
else
cout<<"两个字符串不同源"<<endl;
}
int main(){
string first, second;
cout<<"请输入一个由小写字母组成的字符串"<<endl;
cin>>first;
cout<<"请再次输入一个由小写字母组成的字符串"<<endl;
cin>>second;
compare(first, second);
return 0;
}
题目二
给一个包含n个整数元素的集合a,一个包含m个整数元素的集合b。定义magic操作为,从一个集合中取出一个元素,放到另一个集合里,且操作过后每个集合的平均值都大大于于操作前。
注意以下两点:
- 1)不可以把一个集合的元素取空,这样就没有平均值了
- 2)值为x的元素从集合b取出放入集合a,但集合a中已经有值为x的元素,则a的平均值不变(因为集合元素不会重复),b的平均值可能会改变(因为x被取出了)
问最多可以进行多少次magic操作?
思路:
集合,因此不会存在重复值。
对于集合a和集合b,如果两个集合的平均值相同,则无法进行此操作
实现magic操作的方法是拿出平均值高的那个集合里,值小于该集合的平均值且高于另一个集合的平均值的值,且该值在平均值小的集合中并没有出现过(因为集合中元素不会发生重复)。则会发生magic操作。
实现代码:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//要取得[a,b)的随机整数,使用(rand() % (b-a))+ a;
//要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a;
int CreatRandomNum(){
//随机产生1到100的整数
return (rand() % 100)+1;
}
int magic(vector<int>a, vector<int>b){
int sum_a=0, sum_b=0;
for(auto i : a) sum_a+=i;
for(auto i : b) sum_b+=i;
double ave_a=sum_a/a.size();
double ave_b=sum_b/b.size();
if(ave_a==ave_b) return 0;
sort(a.begin(),a.end());
sort(b.begin(),b.end());
int answer=0;
//从a往b拿
if(ave_a>ave_b){
for(int i=0; i<a.size();i++){
//该值大于b的均值且小于a的均值,且在b中没出现过
if((a[i]>ave_b)&&(a[i]<ave_a)&&(find(b.begin(),b.end(),a[i])==b.end())){
answer++;
}
}
}
//从b往a拿
else{
for(int i=0; i<b.size();i++){
//该值大于a的均值且小于b的均值,且该值在a中没出现过
if((b[i]>ave_a)&&(b[i]<ave_b)&&(find(a.begin(),a.end(),b[i])==a.end())){
answer++;
}
}
}
return answer;
}
int main(){
vector<int>a, b;
int len_a=CreatRandomNum(), len_b=CreatRandomNum();
while(len_a--)
a.push_back(CreatRandomNum());
while(len_b--)
b.push_back(CreatRandomNum());
int answer=magic(a,b);
cout<<answer<<endl;
return 0;
}
题目三
将给定的数转换为字符串,原则如下:1对应 a,2对应b,…..26对应z,
例如12258可以转换为"abbeh", "aveh", "abyh", "lbeh" and "lyh",个数为5,
编写一个函数,给出可以转换的不同字符串的个数。
思路:
暴力递归解思路(配合后面的代码更容易理解):
对于字符串,遍历每个字符:
- 如果当前位置为字符串的结尾位置,则只有一种表达方式——空串。
- 如果当前字符是“0”,则无法转换,因为1111可以转成aaaa,也可以11和11组合。但是字符以0开头,没有对应的字符
- 如果开头不是“0”,且后续有字符。只要该位置不是“0”,则结果sum=1(该位置的字符自己表示一个字母)+余下的组合方式
- 当遍历到字符串的末尾,则结束递归。
动态规划解法——dp只是用来记录每一步的最优解的一个容器
实现代码:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
//产生一个10000-100000的随机数
int CreatRandomNum(){
/*
要取得[a,b)的随机整数,使用(rand() % (b-a))+ a;
要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a;
要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1;
*/
return (rand()%90000)+10000;
}
//暴力递归
int Process(string input, int index){
if(index==input.length()) return 1;
if(input[index]=='0') return 0;
int res=Process(input, index+1);
if(index==input.length()-1) return res;
if(((input[index]-'0')*10+input[index+1]-'0')<27)
res+=Process(input, index+2);
return res;
}
//动态规划
int dp(string input){
//初始长度为input.length()+1,因为有可能会有空串的情况
//应该把该结果放在动态规划数组索引位置为input.length()的位置,因此初始化长度为input.length()+1
vector<int>con(input.length()+1);
//把空串的情况存放在空串会发何时能的对应位置上
//空串的时候,只有一种结果,所以此时的值为1
con[input.length()]=1;
//最后一位如果是0,则此处无解,否则此处是一种字母,结果为1
con[input.length() - 1] = input[input.length() - 1] == '0' ? 0 : 1;
for(int i=input.length()-2; i>=0; i--){
//此时无法代表任何字符,因此次违章的结果为0
if (input[i] == '0') con[i] = 0;
else
//当前字符不是"0"。如果此位置和下一个位置组合的值小于27,说明还能组合出一个结果
con[i] = con[i + 1] + (((input[i] - '0') * 10 + (input[i + 1] - '0')) < 27 ?
con[i + 2] : 0);
}
return con[0];
}
int main(){
//把数字转成字符串
string input=to_string (CreatRandomNum());
//暴力递归
//cout<<Process(input, 0)<<endl;
//动态规划
//cout<<dp(input)<<endl;
cout<<input<<endl;
Process(input, 0)==dp(input)?cout<<"good"<<endl:cout<<"fucking !!! fuck!!!"<<endl;
return 0;
}
未完待续 2019.2.27