华为机试
- 1.两数的最小公倍数
- 2.求一个数的立方根
- 3.字符串逆序
- 4.统计正均负数II
- 5.字符串划分
- 6.最长递增子序列(not)
- 7.统计字符(not)
- 8.输入整型数组和排序标识,对其元素按照升序或降序进行排序
- 9.等差数列
- 10.自守数
- 11.给字符串中的数字加*
- 12.往左往下走求方法(not)
- 13.合法ip(*)
- 14.扑克牌比大小
- 15.密码强度等级
- 16.求最大连续bit数
- 17.字符串运用-密码截取
- 18. 二维数组操作
- 19. 将真分数分解为埃及分数(not)
- 20. 字符串匹配
- 21. 整形数组合并
- 22. 计算字符串串的相似度(not)
- 23. 超长正整数相加
- 24. 火车进站.栈(not)
- 24.尼科切斯定理
- 25.公共子串计算
- 26.参数解析
- 27. 计算日期到天数的转换
- 28.百钱买百鸡问题
- 29.字符串通配符(not)
- 30.矩阵乘法计算量估计(not)
1.两数的最小公倍数
题目
最小公倍数=两数之乘除以其最大公因数;
方法一:笨方法:先找最大公因数
int maxFactor(int num1,int num2)
{
if(num1<=0 || num2<=0)
return 0;
int max=0;
if(num1%num2==0 || num2%num1==0)
{
max=num1<num2?num1:num2;
return max;
}
int temp=num2>num1?num1:num2;
for(int i=1;i<=temp/2;i++)
{
if( num1%i==0 && num2%i==0 && i>max)
max=i;
}
return max;
}
方法二:
//while(scanf("%d\n%d",&a,&b)!=EOF) //循环输入测试用例
fflush(stdin); //清除标准输入的内容;学到了
int i=1;
if(a<b) //交换ab;
while(1){
if((i*a)%b==0) //输出返回结束;
i++;
}
2.求一个数的立方根
题目
方法一:笨方法
double getCubeRoot(double num)
{
double a=1.0;
for(double i=1.0;i<num/3;i=i+a)
{
//if(i*i*i==num)
if(num-i*i*i<1e-4 && 0<num-i*i*i) //该处和下面的if判断任选其一;
{
return i;
}
else if(i*i*i>num)
{
i=i-1*a; //类似于深度学习的学习率
a=a/10.0;
//if(a<0.001) //疑惑为什么不加入该判断时,将进入死循环,
// return i;
}
}
return -1;
}
cout<<setprecision(2)<<res<<endl; //输出保留两位有效数字;
方法二:数学方法、牛顿迭代公式
#include<bits/stdc++.h>
using namespace std;
int main()
{
int input;
while(cin>>input)
{
double x=1.0;
for(;abs(x*x*x-input)>1e-4;x=2*x/3+input/(3*x*x));
//根据牛顿迭代公式:
//平方根:x=x/2+input/(2*x);
//立方根:x=2*x/3+input/(3*x*x));
cout<<setprecision(2)<<x<<endl;
}
return 0;
}
3.字符串逆序
题目
本题不难,就是在如何读取数据上注意一下
//读取字符
char ch[1001];
cin.getline(ch,1000);
//读取一行赋值给字符串
string str;
getline(cin,str);
//一行读取n个数
while(cin>>a)
{
vec.push_back(a);
if(cin.get()=='\n')
break;
}
4.统计正均负数II
题目2
题目分类较难;但是我感觉一般,所以不要被题目分类吓住;
//感觉需要主要如何控制输出精度,以下保留小数点后一位
printf("%0.1f",res);
cout<<fixed<<setprecision(1)<<res<<endl;
5.字符串划分
题目
下面的方法不通过原因:因为系统后台要测试多组数据如果这写,那么将只测试一组,导致输入后面测试用例时,输出为空; ---->在这卡了半天;
将cin>>n改为while(cin>>n)即可;
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
string str;
while(n-->0)
{
cin>>str;
int i=0;
for(;i<str.size();i++)
{
cout<<str[i];
if((i+1)%8==0)
cout<<endl;
}
if(i%8!=0){
while(i%8!=0)
cout<<"0",i++;
cout<<endl;
}
}
return 0;
}
可以对上面进行简单改进,循环判断时,每次加8,这这样处理一个字符串的时间就缩小了8倍;
6.最长递增子序列(not)
题目
方法一:使用两个数组,一个保持原始数据,一个保持排序好的;然后对两个数组使用动态规划(类似最长公共子序列的求法),但是这里有重复的数字,所以最后再用dp[n][n]-重复的数据; ------->但是结果不对,不符号最长公共子序列的形式;
对上面的修改:我先根据排序好的数组numbak对numbak和nums进行去重,去重规则为每次取出最前面相同的那个数;然后再对去重后的数组进行动态规划(注意此时动态数组的len已经改变,变小了);------->通过率为60%;
- 我知道问题原因了:再对数组去重时,先去前面的,导致这种情况:1 2 3 61 5 7去重后 2 3 6 1 5 7了,最长递增子序列由5变为7,我也考虑由后往前去重,同样会出现那些的问题;
//inline int max1(int a,int b)省略、篇幅太长了
int main()
{
int n;
while(cin>>n){
int a;
vector<int> nums;
vector<int> numbak;
for(int i=0;i<n;i++)
{
cin>>a;
nums.push_back(a);
numbak.push_back(a);
}
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size()-1;i++)
{
vector<int>::iterator iter;
if(nums[i]==nums[i+1])
{
for(int j=0;j<numbak.size();j++)
{
if(numbak[j]==nums[i])
{
iter=find(numbak.begin(),numbak.end(),numbak[j]);
numbak.erase(iter);
break;
}
}
iter=find(nums.begin(),nums.end(),nums[i]);
i--; //因为每次删除一个元素,nums.size()都会变小,所以保持i不变
nums.erase(iter);
}
}
int len=nums.size();
int arr[len+1][len+1];
for(int i=0;i<len+1;i++)
{
arr[0][i]=0,arr[i][0]=0;
}
for(int i=1;i<len+1;i++)
for(int j=1;j<len+1;j++)
{
if(nums[i-1]==numbak[j-1])
arr[i][j]=arr[i-1][j-1]+1;
else
arr[i][j]=max1(arr[i-1][j],arr[i][j-1]);
}
int res=arr[len][len];
cout<<res<<endl;
}
return 0;
}
方法二:大神的写法,真是厉害;二分查找法;
int main()
{
int n;
while(cin>>n)
{
vector<int> vec;
int a;
for(int i=0;i<n;i++)
{
//vec的数据一定是有序的
cin>>a;
if(vec.size()==0)
vec.push_back(a);
else if(lower_bound(vec.begin(),vec.end(),a)==vec.end())
vec.push_back(a);
//如果a[i]不在res.begin()到res.end()之间,即a[i]比res每个数都大;如vec;
else //否则,表明a[i]在上述范围内,返回第一个>=a[i]的那个数的迭代器;
*(lower_bound(vec.begin(),vec.end(),a))=a;
}
cout<<vec.size()<<endl;
}
return 0;
}
//二插查找算法三种:
//1.lower_bound(起始地址,结束地址,要查找的数值为a) 返回的是数值 第一个 出现的位置。
//lower_bound如果a<结束地址值,但是没有与a相等的,就返回第一个比a大元素的迭代器;即>=a的那个数的迭代器;
//如在2,7查找1:将返回2的迭代器; 在1 4 7中查找5,将返回7的迭代器;
//2.upper_bound(起始地址,结束地址,要查找的数值) 返回的是数值 最后一个 出现的位置。
//3.binary_search(起始地址,结束地址,要查找的数值) 返回的是是否存在这么一个数,是一个bool值。
方法三:动态规划
和我想一起去了,只是我没实现出来,很可惜,dp[i]为前面比它小的那个数的dp[i];
int main()
{
int n;
while(cin>>n)
{
int a[n];
for(int i=0;i<n;i++)
cin>>a[i];
vector<int> res(n,1);
int maxcount=n>0?1:0;
for(int i=1;i<n;i++)
{
for(int j=0;j<i;j++)
if(a[j]<a[i])
res[i]=max(res[i],res[j]+1);
if(res[i]>maxcount)
maxcount=res[i];
}
cout<<maxcount<<endl;
}
return 0;
}
7.统计字符(not)
题目
方法一:双哈希法,因为题目要求要是两个字符数量一样,需要按ASCLL码(128位)进行打
印;
这类题目做的相对较少;双排序;
int main()
{
char str[60000];
int len=0;
while(cin>>str)
{
int hash[128]={
0};//为了完成对统计数的排序
int hash2[128]={
0}; //为了打印时与hash进行映射
len=strlen(str);
for(int i=0;i<len;i++)
hash[str[i]]++, hash2[str[i]]++;
sort(hash,hash+128);//排序数据后0 0 0... 0 0 1 2 3....
sort(str,str+len); //
//对字符串排序按ASCLL码排序,为了处理相同数量按ASCLL打印;
for(int i=127;i>=0;i--)
{
if(hash[i]==0) break;
for(int j=0;j<len;j++)
{
//如果该字符的出现的次数hash2[str[j]]等于最大次数hash[i]
if(hash2[str[j]]==hash[i])
{
cout<<str[j]; //输出字符
hash2[str[j]]=0; //清除该字符的统计数量,因为如果后面的字符数量也为hash2[str[j]],那么打印的就是str[j]了,重复打印;
break;
}
}
}
cout<<endl;
}
return 0;
}
8.输入整型数组和排序标识,对其元素按照升序或降序进行排序
题目
注意题目中的输入细节:
先输入一个数
再输入一行数
再输入表示tag(0或1)
//可以调用STL的函数sort更快
sort(v1.begin(),v1.end()); //greater<int>(),less<int>();
int arr[n];
sort(arr,arr+n);
//反转
reverse(v1.begin(),v1.end(