华为机试题 11-20

数字颠倒

#include<bits/stdc++.h>
using namespace std;
int main () {
    int nums;
    cin >> nums;
    string str = to_string(nums);
    reverse(str.begin(),str.end());
    cout << str;
    return 0;
}
  • to_string(int n)将数值转化为字符串。返回对应的字符串。
  • reverse() 功能是逆序(或反转),多用于字符串、数组、容器。头文件是#include reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数无返回值

句子逆序

最近reverse[a,b)很常用,我的思路,两次反转,第一次全局逐个字母反转,第二次一空格为分割逐个单词反转

  • reverse(s.begin()+j,s.begin()+i);局部reverse()

简洁方法,按单词接受。边接收边逆序

#include<bits/stdc++.h>
using namespace std;
 
int main() {
    string str, res;
    while(cin >> str) {
        str += " " +res;
        res = str;
    }
    cout << res << endl;
    return 0;
}

字符串排序

vector容器

vector<string>  s

此时s[i]中不是一个char的字符,而是一个string型的单词!!

坐标移动

速度慢,思路感觉没啥大问题

#include<bits/stdc++.h>
using namespace std;
int main(){
    pair<int , int> a(0,0);
    string s;
    cin>>s;
    vector<string> str;
    int j=0,i=0,len=0;//如何切片?
    while(s[i]){
        if(s[i]==';'){
            str.push_back(s.substr(j,i-j));
            j=i+1;
            len++;
        }
        i++;
    }
    for(int i=0;i<len;i++){
        string h=str[i];
        int x;
        if(h.size()==2){
            if(h[1]>='0'&&h[1]<='9') x=(int)(h[1]-'0');
            else continue;
        }
        else if(h.size()==3){
            if(h[1]>='0'&&h[1]<='9'&&h[2]>='0'&&h[2]<='9') 
                x=(int)(h[1]-'0')*10+(int)(h[2]-'0');
            else continue;
        }
        else{
            continue;
        }
        if(h[0]=='A'){
            a.first-=x;
        }
        if(h[0]=='D'){
            a.first+=x;
        }
        if(h[0]=='W'){
            a.second+=x;
        }
        if(h[0]=='S'){
            a.second-=x;
        }
       
    }
    cout<<a.first<<","<<a.second<<endl;
}

密码验证合格程序

islower(char c) 是否为小写字母
isuppper(char c) 是否为大写字母
isdigit(char c) 是否为数字
isalpha(char c) 是否为字母
isalnum(char c) 是否为字母或者数字
toupper(char c) 字母小转大
tolower(char c) 字母大转小
compare()
判断是否有长度超过3的相同子串没有思路

        string target;
        int isFound = 0;
        for (int i = 0; i < s.size()-3; i ++){
            for (int j = i + 3; j < s.size()-3; j ++){
                // 如果字符串相同
                if (0 == s.compare(i, 3, s, j, 3)){
                    isFound = 1;
                    break;
                }
            }
            if (isFound) break;
        }
        if (isFound)
            cout << Err << endl;
        else
            cout << Ok << endl;
 
    }
  • string中的字符串比较
  • str1与str2比较:str1.compare(str2)
  • tr1的子串(从索引3开始,包含4个字符)与str2进行比较
    str1.compare(3,4,str2)
  • str1指定子串与str2的指定子串进行比较
    str1.compare(3,4,str2,3,4)

H16 购物单

0-1背包问题

问题描述:有一个背包可以装物品的总重量为W,现有N个物品,每个物品中w[i],价值v[i],用背包装物品,能装的最大价值是多少?、
定义状态转移数组dp[i][j],表示前i个物品,背包重量为j的情况下能装的最大价值
例如,dp[3][4]=6,表示用前3个物品装入重量为4的背包所能获得的最大价值为6,此时并不是3个物品全部装入,而是3个物品满足装入背包的条件下的最大价值。
状态转移方程:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])
dp[i-1][j]表示当前物品不放入背包,dp[i-1][j-w[i]]+v[i]表示当前物品放入背包,即当前第i个物品要么放入背包,要么不放入背包。

dp = [[0]*(n+1) for _ in range(m+1)]
for i in range(1,m+1):
    for j in range(1,n+1):
        if j-w[i]>=0:
            dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])
        else:
            dp[i][j] = dp[i-1][j]
return dp[m][n]

两种情况:
装不下当前物品,前n个最佳组合与前n-1个一样
装得下当前物品,求两者较大值:
装入——n-1价值加当前价值
不装入——前n个最佳组合与前n-1个一样

若想定义A = [[0,1,2],[3,4]。
vector<vector > A;
for(int i = 0; i < 2; ++i) A.push_back(vector());
A[0].push_back(0);
A[0].push_back(1);
A[0].push_back(2);
A[1].push_back(3);
A[1].push_back(4);

输入的第 1 行,为两个正整数N,m,用一个空格隔开:
(其中 N ( N<32000 )表示总钱数, m (m <60 )为可购买的物品的个数。)
从第 2 行到第 m+1 行,第 j 行给出了编号为 j-1 的物品的基本数据,每行有 3 个非负整数 v p q
(其中 v 表示该物品的价格( v<10000 ), p 表示该物品的重要度( 1 ~ 5 ), q 表示该物品是主件还是附件。如果 q=0 ,表示该物品为主件,如果 q>0 ,表示该物品为附件, q 是所属主件的编号)

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int N, m;
    cin >> N >> m;//钱数 ,个数
    // 由于价格是10的整数倍,处理一下以降低空间/时间复杂度
    N /= 10;
    vector<vector<int> > prices(61, vector<int>(3, 0));        // 价格
    vector<vector<int> > priceMultiplyPriority(61, vector<int>(3, 0));      // 重要程度
    for (int i = 1; i <= m; ++i) {
        int a, b, c;
        cin >> a >> b >> c;
        a /= 10; b *= a;
        if (c == 0) {//主件
            prices[i][0] = a;
            priceMultiplyPriority[i][0] = b;
        } else {
            if (prices[c][1] == 0) {//附件1
                prices[c][1] = a; 
                priceMultiplyPriority[c][1] = b;
            } else {//附件2
                prices[c][2] = a; 
                priceMultiplyPriority[c][2] = b;
            }
        }
    }
    // 使用分组背包
    vector<vector<int> > dp(m+1, vector<int>(N+1, 0));
    for (int i = 1; i <= m; ++i) {
        for (int j = 1; j <= N; ++j) {
            int a = prices[i][0], b = priceMultiplyPriority[i][0];//只有主件价格 重要程度
            int c = prices[i][1], d = priceMultiplyPriority[i][1];
            int e = prices[i][2], f = priceMultiplyPriority[i][2];
            dp[i][j] = j >= a ? max(dp[i-1][j-a] + b, dp[i-1][j]) : dp[i-1][j];
            dp[i][j] = j >= (a+c) ? max(dp[i-1][j-a-c] + b + d, dp[i][j]) : dp[i][j];
            dp[i][j] = j >= (a+e) ? max(dp[i-1][j-a-e] + b + f, dp[i][j]) : dp[i][j];
            dp[i][j] = j >= (a+c+e) ? max(dp[i-1][j-a-c-e] + b + d + f, dp[i][j]) : dp[i][j];
        }
    }
    cout << dp[m][N] * 10 << endl;
}

识别有效IP地址

思路:

按行读取输入,根据字符‘~’ 将IP地址与子网掩码分开
查看子网掩码是否合法。
    合法,则继续检查IP地址
    非法,则相应统计项+1,继续下一行的读入 
查看IP地址是否合法
    合法,查看IP地址属于哪一类,是否是私有ip地址;相应统计项+1
    非法,相应统计项+1 
#include<iostream>
#include<string>
#include<vector>
using namespace std;

int main(){
    vector<int> arr(7, 0); //分别对应题目的7个类别
    string s;
    while(getline(cin, s)){
        int n = s.length();
        vector<int> ips; //记录ip地址的数字
        bool bad = false;
        bool isnum = false;
        int num = 0;
        for(int i = 0; i < n; i++){ //遍历该ip字符串
            if(s[i] == '.' || s[i] == '~'){ //以.或者~分割
                if(isnum){
                    if(num > 255){
                        bad = true; //错误ip,数字不能超过255
                        break;
                    }
                    ips.push_back(num);
                    isnum = false;
                    num = 0;
                }else{
                    arr[5]++; //错误地址
                    bad = true;
                    break;
                }
            }else if(s[i] >= '0' && s[i] <= '9'){
                isnum = true;
                num = num * 10 + s[i] - '0'; //计算数字
            }else{
                arr[5]++;
                isnum = false; //错误地址,数字部分还有非数字
                bad = true;
                break;
            }
        }
        if(isnum)
            ips.push_back(num); //最后一个数字
        if(ips[0] == 0 || ips[0] == 127 || bad) 
            continue; //忽略0或者127开头的地址,错误ip已经统计了过了,可以忽略
        int mask = 4; //查看掩码的数字
        while(mask < 8 && ips[mask] == 255)
            mask++;  //找到掩码第一个不全为1的数
        if(mask == 8){ //掩码全1也是不合法
            arr[5]++;
            continue; 
        }else if(ips[mask] == 254 || ips[mask] == 252 || ips[mask] == 248 || ips[mask] == 240 || ips[mask] == 224 || ips[mask] == 191 || ips[mask] == 128)
            mask++; //各类掩码含1的最后一位
        while(mask < 8 && ips[mask] == 0)
            mask++;
        if(mask != 8){ //掩码后半部分不能有1
            arr[5]++;
            continue;
        }
        if(ips[0] >= 1 && ips[0] <= 126)
            arr[0]++; //A类地址
        else if(ips[0] >= 128 && ips[0] <= 191) 
            arr[1]++; //B类地址
        else if(ips[0] >= 192 && ips[0] <= 223) 
            arr[2]++; //C类地址
        else if(ips[0] >= 224 && ips[0] <= 239) 
            arr[3]++; //D类地址
        else if(ips[0] >= 240 && ips[0] <= 255) 
            arr[4]++; //E类地址
        if(ips[0] == 10) 
            arr[6]++; //私有地址10开头的
        else if(ips[0] == 172 && (ips[1] >= 16 && ips[1] <= 31)) 
            arr[6]++; //私有地址172.16.0.0-172.31.255.255
        else if(ips[0] == 192 && ips[1] == 168) 
            arr[6]++; //私有地址192.168.0.0-192.168.255.255
    }
    for(int i = 0; i < 7; i++){ //输出
        cout << arr[i];
        if(i != 6)
           cout << " ";
    }
    cout << endl;
    return 0;
}

情况比较复杂的分类问题

  • 接受数据,每段放入vector数组中
  • 判断掩码,手算出全1情况——254,242,248…

简单错误记录

  • for(auto a:b)中b为一个容器,效果是利用a遍历并获得b容器中的每一个值,但是a无法影响到b容器中的元素。
  • for(auto x:deq)
#include<bits/stdc++.h>
using namespace std;
int main(){
    string str;
    map<string, int> info;
    deque<string> deq;
    while(getline(cin,str)){
        str=str.substr(str.find_last_of('\\')+1);
        int pos=str.find_last_of(' ');
        if(pos>16){
            str=str.substr(pos-16);
        }
        if(info.find(str)==info.end()){
            deq.push_back(str);//队尾增加
        }
        ++info[str];//数字加1
        if(deq.size()>8) deq.pop_front();
    }
    for(auto x:deq){
        cout << x << " " << info[x] << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值