华为机试题21-30记录

简单密码

  • 字母判断
    islower(char c) :是否为小写字母
    isupper(char c): 是否为大写字母
    isdigit(char c) :是否为数字
    isalpha(char c) :是否为字母
    isalnum(char c): 是否为字母或者数字

  • 大小写转换
    toupper(char c): 字母小转大
    tolower(char c) :字母大转小

更好思路,设置密码字典

string Password_Transformation(string str)
{
    //字典法:考虑两个字典,一个是明文字典 a[],另一个是明文对应的加密字典 b[]。
    //然后采用字典元素对应的方法,做加密或解密,实现方法为“字典下标对应索引以及元素匹配”。
    char a[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"}; //非必要的参照字典
    char b[] = {"bcdefghijklmnopqrstuvwxyza222333444555666777788899990123456789"}; //字符输出对应字典
    int len = str.size();
    for (int i = 0; i < len; i++)
    {
        //小写字母转数字
        if ((str[i] >= 'a') && (str[i] <= 'z'))
        {
            str[i] = b[str[i] - 'a' + 26];
        }
        //大写字母转小写
        if ((str[i] >= 'A') && (str[i] <= 'Z'))
        {
            str[i] = b[str[i] - 'A'];
        }
        //数字不用转换,保持原样
    }
    return  str;
}

汽水瓶

知道这题优秀的解法,我真是裂开了。

题目描述中有讲到:剩2个空瓶子时,可以先找老板借一瓶汽水,喝掉这瓶满的,喝完以后用3个空瓶子换一瓶满的还给老板。

也就是说2个空瓶子即可换一瓶汽水喝,而且喝完之后手里也没有空瓶子。求解时直接把空瓶数除以2,即可得到正解。

删除字符串

笨蛋方法:第一次遍历,哈希表统计出现次数,第二次遍历哈希表,寻找最小值,第三次遍历原字符串,个数大于min输出!

#include<bits/stdc++.h>
using namespace std;
int main(){
    string s;
    cin>>s;
    int a[26];
    memset(a, 0, sizeof(a));
    int min=1000;
    for(int i=0;i<s.length();i++){
        int t=s[i]-'a';
        a[t]++;
    }
    
    for(int i=0;i<26;i++){
        if(a[i]!=0&&a[i]<min){
            min=a[i];
        }
    }
    for(int i=0;i<s.length();i++){
        int t=s[i]-'a';
        if(a[t]>min)cout<<s[i];
    }
    
    return 0;

}

合唱队————最长递增子序列

就是自左向右求出最长递增子序列的最优值dp数组,自右向左求出最长递减子序列的最优值dp数组,两者对位相加-1,其中的最大值,就是整个合唱队留在场上的人数的最大值,因此也就是出列的最小值。
dp的这部分,需要做三步:

  • 定义dp的含义,比如这一题,dp是一个数组,dp[i]表示的是,在确定必须选择v[i]的情况下,表示v[0…i]中的最长递增子序列的长度。
  • 写出递归式或者状态转换方程:dp[i] = max(dp[j]) + 1 当v[i]>v[j]时
  • 定义最优值,这里的最优值可能是dp中的某一项。
    dp 0 1 2
    max 1 1 2
    n个数,n种情况,如果只有第一个数,则最长递增(不要求连续)只能是1,dp[0]=1,如果有两个数,180,180,先设dp[1]=1,然后比较a[0]==a[1],这样不加入循环,三个数,180 180 182,令dp[2]=1,182>180(a[2]>a[0]),dp[2]=max(dp[2],dp[0]+1)==dp[0]+1=2;然后继续!
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin>>n;
    int a[n];
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    int dp1[n],dp2[n];
    memset(dp1, 0, sizeof(dp1));
    memset(dp2, 0, sizeof(dp2));
    for(int i=0;i<n;i++){
        dp1[i]=1;
        for(int j=0;j<i;j++){
            if(a[i]>a[j]){
                dp1[i]=max(dp1[i],dp1[j]+1);
            }
        }
    }
    for(int i=n-1;i>=0;i--){
        dp2[i]=1;
        for(int j=n-1;j>i;j--){
            if(a[i]>a[j]){
                dp2[i]=max(dp2[i],dp2[j]+1);
            }
        }
    }
    int len=0;
    for(int i=0;i<n;i++){
        if(len<dp1[i]+dp2[i]-1){
            len=dp1[i]+dp2[i]-1;
        }
    }
    cout<<n-len<<endl;
    return 0;
}

H25 数据分类处理

  • string:npos是个特殊值,说明查找没有匹配
#include <bits/stdc++.h>

using namespace std;

signed main() {
    int n;
    cin >> n;
    vector<string> I(n);
    for (auto &it : I) cin >> it;
    // 这个是把我们的I数组输入进去
    int m;
    cin >> m;
    set<int> st;
    for (int i = 1; i <= m; i++) {
        int tmp;
        cin >> tmp;
        st.insert(tmp);
    }
    // 这个实现了我们R数组的去重和排序
    int res = 0;
    for (auto &it : st) {
        int cnt = 0;
        bool okk = false;
        // cnt是有多少个
        // okk是我们是否找到
        for (auto &it1 : I) {
            if (it1.find(to_string(it)) != string::npos) {//string:npos是个特殊值,说明查找没有匹配
                cnt += 1;
                if (okk == false) {
                    res += 1;
                    okk = true;
                }
                // 如果找到了我们存入数组
            }
        }
        if (cnt != 0) {
            res += 1;
            for (int i = 0; i < n; i++) {
                if (I[i].find(to_string(it)) != string::npos) {
                    res += 2;
                }
            }
            // 我们每一次把我们的下标和我们的值存入
        }
    }
    cout << res << " ";
    for (auto &it : st) {
        int cnt = 0;
        bool okk = false;
        // cnt是有多少个
        // okk是我们是否找到
        for (auto &it1 : I) {
            if (it1.find(to_string(it)) != string::npos) {
                cnt += 1;
                if (okk == false) {
                    cout << it << " ";
                    okk = true;
                }
                // 如果找到了我们存入数组
            }
        }
        if (cnt != 0) {
            cout << cnt << " ";
            for (int i = 0; i < n; i++) {
                if (I[i].find(to_string(it)) != string::npos) {
                    cout << i << " " << I[i] << " ";
                }
            }
            // 我们每一次把我们的下标和我们的值存入
        }
    }
    cout << "\n";
    return 0;
}

H27 查找兄弟单词

!set容器的使用,set容器可以不重复的自动排序存储

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin>>n;
    vector<string> s;
    vector<string> q;
    string str;
    for(int i=0;i<n;i++){
        cin>>str;
        s.push_back(str);
    }
    string b;cin>>b;
    string word=b;//需要复制b,否则第一次循环后b就改变顺序了
    int k;cin>>k;
    int len=b.length();
    for(int i=0;i<n;i++){
        if(s[i].length()==len&&s[i]!=word){
            string str2=s[i];
            sort(str2.begin(),str2.end());
            sort(b.begin(),b.end());
            if(str2==b){
                q.push_back(s[i]);
            }
        }
    }
    sort(q.begin(),q.end());
    cout<<q.size()<<endl;
    if(k<q.size()){
        cout<<q[k-1]<<endl;
    }
    
    
    return 0;
}

*H28 素数伴侣

我们对于统计的数组分成奇数数组和偶数数组,如果其中有一个数组为空,则不可能构成“素数伴侣”。
然后就相当于是左边一些奇数元素的点,要连到右边偶数元素上面,这就是二分图连线最多的问题,我们可以用匈牙利算法。
首先我们遍历左边奇数数组,对每一个元素都查找能否在偶数数组中找到配对的数,查找时我们遍历偶数数组,如果该偶数能和这个奇数匹配,且在这一轮这个偶数没被用过,我们再检查这个match数组(表示现阶段偶数匹配的对象),如果match数组中这个偶数没有匹配对象,或者递归查找这个匹配对象可以有其他的偶数匹配,那我们修改该匹配对象为这个奇数,代表能找到匹配。

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
bool isprime(int num){
    int k=sqrt(num);
    for(int i=2;i<=k;i++){//素数检查根号n
        if(num%i==0){
            return false;
        }
    }
    return true;
}
bool find(int num,vector<int>& evens,vector<bool>& used,vector<int>& match){
    for(int i=0;i<evens.size();i++){
        if(isprime(num+evens[i])&&!used[i]){
            used[i]=true;
            if(match[i]==0||find(match[i],evens,used,match)){
                match[i]=num;
                return true;
            }
        }
    }
    return false;
}
int main(){
    int n;
    while(cin>>n){
        vector<int> odds;
        vector<int> evens;
        vector<int> nums(n);
        for(int i=0;i<n;i++){
            cin>>nums[i];
            if(nums[i]%2==0){
                evens.push_back(nums[i]);
            }
            else{
                odds.push_back(nums[i]);
            }
        }
        int count=0;
        if(odds.size()==0||evens.size()==0){
            cout<<count<<endl;
            continue;//继续下一次while循环
        }
        vector<int> match(evens.size(),0);//统计每个偶数的配对是哪个奇数,不重置
        for(int i=0;i<odds.size();i++){
            vector<bool> used(evens.size(),false);//每次奇数都会重置used数组
            if(find(odds[i],evens,used,match)){
                count++;
            }
        }
        cout<<count<<endl;
    }
    return 0;
}

例子解释:
4
2 5 6 13
奇数5 13
偶数6 2
第一次遍历
5——6 used ok 检查match[0]==0 count++;配对match[0]=5

第二次,重置used数组
13——6 质数,used[0] ok,match[0]=5,if再find循环
5——6,质数,!used[0]
5——2,质数 used[1] ok,match[1]==0;此时令match[1]=2;
if结束,return true ,此时match[0]=13;cout++;

H29 字符串加减密

  • isalpha(s)判断是否是字母
  • isalnum(s)判断是否是字母或数字
  • toupper(i)小写变大写
  • tolowwer(i)大写变小写(±32)

H30 字符串合并处理

第三步:对排序后的字符串中的’0’‘9’、‘A’‘F’和’a’~'f’字符,需要进行转换操作。
转换规则如下:
对以上需要进行转换的字符所代表的十六进制用二进制表示并倒序,然后再转换成对应的十六进制大写字符(注:字符 a~f 的十六进制对应十进制的10~15,大写同理)。
如字符 ‘4’,其二进制为 0100 ,则翻转后为 0010 ,也就是 2 。转换后的字符为 ‘2’。
如字符 ‘7’,其二进制为 0111 ,则翻转后为 1110 ,对应的十进制是14,转换为十六进制的大写字母为 ‘E’。
如字符 ‘C’,代表的十进制是 12 ,其二进制为 1100 ,则翻转后为 0011,也就是3。转换后的字符是 ‘3’。

根据这个转换规则,由第二步生成的字符串 “abcedf” 转换后会生成字符串 “5D37BF”。

string trans(string s){
    for(int i=0;i<s.length();i++){
        int a;
        if(s[i]>='0'&&s[i]<='9'){
            a=s[i]-'0';
        }
        else if(s[i]>='a'&&s[i]<='f'){
            a=s[i]-'a'+10;
        }
        else if(s[i]>='A'&&s[i]<='F'){
           a=s[i]-'A'+10;
        }
        else continue;//不输入这个不行
        string bi="";
        while(a){
            bi+=a%2+'0';
            a/=2;
        }
        while(bi.size()<4){
            bi+='0';
        }
        int y=0;
        for(int i=3;i>=0;i--){
            int k=pow(2,3-i);
            y+=(bi[i]-'0')*k;
        }
        if(y>9){
            s[i]='A'+y-10;
        }
        else{
            s[i]='0'+y;
        }
    }
    return s;
}

最后还是使用了最朴素的方法,手算模拟转换二进制!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值