华为上机题汇总(五)

华为上机题汇总(五)

注:编译环境为Visual Studio 2012,答案仅供参考。

目录

第二十一题

21.通过键盘输入100以内正整数的加、减运算式,请编写一个程序输出运算结果字符串。
输入字符串的格式为:“操作数1 运算符 操作数2”,“操作数”与“运算符”之间以一个空格隔开。

补充说明:
1. 操作数为正整数,不需要考虑计算结果溢出的情况。
2. 若输入算式格式错误,输出结果为“0”。

示例
输入:“4 + 7” 输出:“11”
输入:“4 - 7” 输出:“-3”
输入:“9 ++ 7” 输出:“0” 注:格式错误

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

bool isNumber(const string &s , int &num){
    int sum = 0;
    for (auto begin = s.rbegin();begin != s.rend();begin++)
    {
        if (*begin < '0' || *begin > '9')
        {
            return false;
        }
        sum += (*begin - '0') * pow(10,begin - s.rbegin());
    }
    num = sum;
    return true;
}

int caculate(const string &s){
    if (s.empty()) return 0;
    auto begin = s.begin();

    vector<string> v;
    while (begin != s.end())
    {
        auto ahead = begin + 1;
        while (ahead != s.end() && *ahead != ' ')
        {
            ahead++;
        }
        string tmp(begin,ahead);
        v.push_back(tmp);
        if (ahead != s.end()) ahead++;
        begin = ahead;
    }
    if (v.size() != 3) return 0;
    int num1,num2;
    if (!isNumber(v[0],num1) || !isNumber(v[2],num2) || v[1].size() != 1) return 0;

    if (v[1] == "+")
    {
        return num1 + num2;
    }
    else if (v[1] == "-")
    {
        return num1 - num2;
    }
    return 0;
}

int main()
{
    string input;
    getline(cin,input);
    cout << caculate(input) << endl;
    return 0;
}

第二十二题

22.IP地址匹配(60分)
问题描述:
在路由器中,一般来说转发模块采用最大前缀匹配原则进行目的端口查找,具体如下:
IP地址和子网地址匹配:
IP地址和子网地址所带掩码做AND运算后,得到的值与子网地址相同,则该IP地址与该子网匹配。

比如:
IP地址:192.168.1.100
子网:192.168.1.0/255.255.255.0,其中192.168.1.0是子网地址,255.255.255.0是子网掩码。
192.168.1.100&255.255.255.0 = 192.168.1.0,则该IP和子网192.168.1.0匹配

IP地址:192.168.1.100
子网:192.168.1.128/255.255.255.192
192.168.1.100&255.255.255.192 = 192.168.1.64,则该IP和子网192.168.1.128不匹配

最大前缀匹配:
任何一个IPv4地址都可以看作一个32bit的二进制数,比如192.168.1.100可以表示为:11000000.10101000.00000001.01100100,
192.168.1.0可以表示为11000000.10101000.00000001.00000000
最大前缀匹配要求IP地址同子网地址匹配的基础上,二进制位从左到右完全匹配的位数尽量多(从左到右子网地址最长)。比如:
IP地址192.168.1.100,同时匹配子网192.168.1.0/255.255.255.0和子网192.168.1.64/255.255.255.192,
但对于子网192.168.1.64/255.255.255.192,匹配位数达到26位,多于子网192.168.1.0/255.255.255.0的24位,
因此192.168.1.100最大前缀匹配子网是192.168.1.64/255.255.255.192。

请编程实现上述最大前缀匹配算法。
要求实现函数:
void max_prefix_match(const char *ip_addr, const char *net_addr_array[], int *n)
【输入】ip_addr:IP地址字符串,严格保证是合法IPv4地址形式的字符串
net_addr_array:子网地址列表,每一个字符串代表一个子网,包括子网地址和掩码,
表现形式如上述,子网地址和子网掩码用’/’分开,严格保证是
合法形式的字符串;如果读到空字符串,表示子网地址列表结束
【输出】n:最大前缀匹配子网在*net_addr_array[]数组中对应的下标值。如果没有匹配返回-1
示例
输入:
ip_addr = “192.168.1.100”
net_addr_array[] =
{
“192.168.1.128/255.255.255.192”,
“192.168.1.0/255.255.255.0”,
“192.168.1.64/255.255.255.192”,
“0.0.0.0/0.0.0.0”,
“”
}
输出:n = 2

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

void convert(const char *ip,vector<int> &v){
    const char *begin = ip, *ahead;
    while (*begin != '\0')
    {
        ahead = begin + 1;
        while (*ahead != '\0' && *ahead != '.' && *ahead != '/')
        {
            ahead++;
        }
        string tmp(begin,ahead);
        v.push_back(stoi(tmp));
        if (*ahead == '\0') break;
        begin = ++ahead;
    }
}

int match(const char *ip, const char *net){
    vector<int> vIp;
    vector<int> vNet;
    convert(ip,vIp);
    convert(net,vNet);

    for (int i = 0; i < 4; i++)
    {
        int tmp = vIp[i] & vNet[4+i];
        if (tmp != vNet[i])
        {
            return -1;
        }
    }

    int matchByte = 0;
    for (int i = 0; i < 4; i++)
    {
        if (vIp[i] == vNet[i])
        {
            matchByte += 8;
            continue;
        }

        int tmp = vIp[i] ^ vNet[i];
        int index = 0;
        for (int i = 7; i > 0; i--)
        {
            if (tmp & 1)
            {
                index = i;
            }
            tmp >>= 1;
        }
        matchByte += index;
        break;
    }
    return matchByte;
}

void max_prefix_match(const char *ip_addr, const char *net_addr_array[], int *n){
    int index = 0, maxIndex = -1, maxByte = -1;
    while (*net_addr_array != "")
    {
        int matchByte = match(ip_addr,*net_addr_array++);
        if (matchByte > maxByte)
        {
            maxIndex = index;
            maxByte = matchByte;
        }
        index++;
    }
    *n = maxIndex;
}

int main()
{
    const char * ip_addr = "192.168.1.100";
    const char * net_addr_array[] = {"192.168.1.128/255.255.255.192",
                               "192.168.1.0/255.255.255.0",
                               "192.168.1.64/255.255.255.192",
                               "0.0.0.0/0.0.0.0",
                               ""};
    int n = 0;
    max_prefix_match(ip_addr,net_addr_array,&n);
    cout << n << endl;
    return 0;
}

第二十三题

23.编写一个程序,实现排序算法,从小到大输出,数字间以逗号分隔,所有数字为非负整数。数目小于1028;
输入:1,6,3,5
输出:1,3,5,6

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

void sortStr(const string &input, string &output){
    vector<int> v;
    auto begin = input.begin();
    while (begin != input.end())
    {
        auto ahead = begin + 1;
        while (ahead != input.end() && *ahead != ',')
        {
            ahead++;
        }
        string tmp(begin,ahead);
        v.push_back(stoi(tmp));
        if (ahead == input.end()) break;
        begin = ++ahead;
    }

    sort(v.begin(),v.end());

    auto vbegin = v.begin();
    while (vbegin != v.end())
    {
        output += to_string(*vbegin++);
        if (vbegin != v.end())
        {
            output.push_back(',');
        }
    }
}

int main()
{
    string input,output;
    getline(cin,input);
    sortStr(input,output);
    cout << output << endl;
    return 0;
}

第二十四题

24.我们把只包含因子2,3,5的数称为丑数,把1当作第一个丑数,求从小到大的第n个丑数
输入:1都500之间的整数(包含1和500)
输出:第n个丑数。不在1-500输出-1

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

int min(int a, int b , int c){
    int tmp = a < b ? a : b;
    return tmp < c ? tmp : c;
}

int findArglyNum(int n){

    if (n < 1 || n >500)
    {
        return -1;
    }

    vector<int> v(n,1);
    int pos2 = 0, pos3 = 0, pos5 = 0;
    for (int i = 1; i < n; i++)
    {
        v[i] = min(2*v[pos2],3*v[pos3],5*v[pos5]);
        if (v[i] == 2*v[pos2])
        {
            pos2++;
        }
        if (v[i] == 3*v[pos3])
        {
            pos3++;
        }
        if (v[i] == 5*v[pos5])
        {
            pos5++;
        }
    }
    return v[n-1];
}

int main()
{
    int n;
    cin >> n;
    cout << findArglyNum(n) << endl;
    return 0;
}

第二十五题

N个城市(N<=10),从0到9编号,城市间要么有路,要么没路,计算城市A到B之间到底有多少条路。
输入:N A B(1<N<=10,0<=A,B<=9)A为出发城市,B为目的城市。然后n行表示行编号的城市到其他城市有没有路,0表示没有,1表示有路。
输出:A到B有多少条路
输入:3 0 2
1 1 1
1 1 1
1 1 1
输出:2

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

bool canVisit(int index, vector<int> hasVisited){
    for (auto begin = hasVisited.begin();begin != hasVisited.end();begin++)
    {
        if (index == *begin)
        {
            return false;
        }
    }
    return true;
}

int findWay(int start, int end, int n, vector<int> hasVisited, vector<vector<int>> road){
    if (start == end)
    {
        return 1;
    }
    int sum = 0;
    vector<int> v = road[start];
    for (int i = 0; i < n; i++)
    {
        if (!v[i]) continue;
        if (canVisit(i,hasVisited))
        {
            hasVisited.push_back(i);
            sum += findWay(i,end,n,hasVisited,road);
        }
    }
    return sum;
}

int main()
{
    int n, a, b;
    cin >> n >> a >> b;
    vector<vector<int>> road;
    for (int i = 0; i < n; i++)
    {
        vector<int> v;
        for (int j = 0; j < n; j++)
        {
            int x;
            cin >> x;
            v.push_back(x);
        }
        road.push_back(v);
    }
    vector<int> hasVisited;
    hasVisited.push_back(a);

    cout << findWay(a,b,n,hasVisited,road) << endl;
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值