编程之旅-Day42

目录

Day42-学习内容:

1.剑指Offer

面试题54:二叉树的第k个节点

面试题40:最小的k个数

 3.华为机试题

例1:购物单

例2:坐标移动

例3:识别有效IP地址和掩码并进行分类统计


1.剑指Offer

面试题54:二叉树的第k个节点

题目描述:给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8)    中,按结点数值大小顺序第三小结点的值为4。

思路:中序遍历+递归

代码:

class Solution {
public:
    TreeNode* KthNode(TreeNode* pRoot, int k)
    {
        if(pRoot==nullptr||k<=0){
            return nullptr;
        }
        return KthNodeCore(pRoot,k);
    }
    TreeNode* KthNodeCore(TreeNode* pRoot, int &k)
    {
        TreeNode* target=nullptr;
        if(pRoot->left!=nullptr){
            target=KthNodeCore(pRoot->left,k);
        }
        if(target==nullptr){
            if(k==1){
                return pRoot;
            }
            k--;
        }
        if(target==nullptr&&pRoot->right!=nullptr){
            target=KthNodeCore(pRoot->right,k);
        }
        return target;
    }
};

面试题40:最小的k个数

题目描述:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

思路:红黑树实现,采用multiset

代码:

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        int len=input.size();
        if(len<=0||k>len){
            return vector<int>();
        }
        multiset<int,greater<int>> leastNumbers;
        vector<int>::iterator iter=input.begin();
        for(;iter!=input.end();iter++){
            if(leastNumbers.size()<k){
                leastNumbers.insert(*iter);
            }
            else{
                multiset<int,greater<int>>::iterator greatest=leastNumbers.begin();
                if(*iter<(*leastNumbers.begin())){
                    leastNumbers.erase(greatest);
                    leastNumbers.insert(*iter);
                }
            }
        }
        return vector<int>(leastNumbers.begin(),leastNumbers.end());
    }
};

解析:

C++ multiset通过greater、less指定排序方式,实现最大堆、最小堆功能

参考:https://www.cnblogs.com/ficow/p/10045777.html

 3.华为机试题

例1:购物单

题目描述:

王强今天很开心,公司发给N元的年终奖。王强决定把年终奖用于购物,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:

主件 附件
电脑 打印机,扫描仪
书柜 图书
书桌 台灯,文具
工作椅

如果要买归类为附件的物品,必须先买该附件所属的主件。每个主件可以有 0 个、 1 个或 2 个附件。附件不再有从属于自己的附件。王强想买的东西很多,为了不超出预算,他把每件物品规定了一个重要度,分为 5 等:用整数 1 5 表示,第 5 等最重要。他还从因特网上查到了每件物品的价格(都是 10 元的整数倍)。他希望在不超过 N 元(可以等于 N 元)的前提下,使每件物品的价格与重要度的乘积的总和最大。

    设第 j 件物品的价格为 v[j] ,重要度为 w[j] ,共选中了 k 件物品,编号依次为 j 1 , j 2 ,……, j k ,则所求的总和为:

v[j 1 ]*w[j 1 ]+v[j 2 ]*w[j 2 ]+ … +v[j k ]*w[j k ] 。(其中 * 为乘号)

    请你帮助王强设计一个满足要求的购物单。

输入描述:

输入的第 1 行,为两个正整数,用一个空格隔开:N m

(其中 N ( <32000 )表示总钱数, m ( <60 )为希望购买物品的个数。)

从第 2 行到第 m+1 行,第 j 行给出了编号为 j-1 的物品的基本数据,每行有 3 个非负整数 v p q

(其中 v 表示该物品的价格( v<10000 ), p 表示该物品的重要度( 1 5 ), q 表示该物品是主件还是附件。如果 q=0 ,表示该物品为主件,如果 q>0 ,表示该物品为附件, q 是所属主件的编号)

输出描述:

 输出文件只有一个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值( <200000 )。

示例1

输入

1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0

输出

2200

思路:动态规划

代码:

#include <iostream>
#include <string.h>  //包含memset函数

using namespace std;

int main(){
    int v[61];
    int dp[61][32001];
    int q[61];
    int vp[61];
    
    int N,m;
    
    while(cin>>N>>m){
        for(int i=0;i<61;i++){
            memset(dp[i],0,sizeof(dp[i]));
        }
        
        int tmp;
        for(int i=1;i<=m;i++){
            cin>>v[i]>>tmp>>q[i];
            vp[i]=v[i]*tmp;
        }
        
        for(int i=1;i<=m;i++){
            for(int j=1;j<=N;j++){
                if(q[i]==0){
                    if(v[i]<=j){
                         dp[i][j]=max(dp[i-1][j-v[i]]+vp[i],dp[i-1][j]);
                    }
                }
                else{
                    if(v[i]+v[q[i]]<=j){
                         dp[i][j]=max(dp[i-1][j-v[i]]+vp[i],dp[i-1][j]);
                    }
                }
            }
        }
        cout << dp[m][N] << endl;
    }
    return 0;    
}

例2:坐标移动

题目描述:

开发一个坐标计算工具, A表示向左移动,D表示向右移动,W表示向上移动,S表示向下移动。从(0,0)点开始移动,从输入字符串里面读取一些坐标,并将最终输入结果输出到输出文件里面。

输入:

合法坐标为A(或者D或者W或者S) + 数字(两位以内)

坐标之间以;分隔。

非法坐标点需要进行丢弃。如AA10;  A1A;  $%$;  YAD; 等。

下面是一个简单的例子 如:

A10;S20;W10;D30;X;A1A;B10A11;;A10;

处理过程:

起点(0,0)

+   A10   =  (-10,0)

+   S20   =  (-10,-20)

+   W10  =  (-10,-10)

+   D30  =  (20,-10)

+   x    =  无效

+   A1A   =  无效

+   B10A11   =  无效

+  一个空 不影响

+   A10  =  (10,-10)

结果 (10, -10)

输入描述:

一行字符串

输出描述:

最终坐标,以,分隔

示例1

输入

A10;S20;W10;D30;X;A1A;B10A11;;A10;

输出

10,-10

代码:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main(){
    string str;
    while(getline(cin,str)){
        vector<string> v;
        int len=str.length();
        int x=0;
        int y=0;
        
        int keep=0;
        for(int i=0;i<len;i++){
            if(str[i]!=';'){
                keep++;
                continue;
            }
            v.push_back(str.substr(i-keep,keep));  //取keep长度的子串
            keep=0;
        }
        
        for(int i=0;i<v.size();i++){
            int num=0;
            if(v[i].length()==3&&(v[i][1]>='0'&&v[i][1]<='9')&&(v[i][2]>='0'&&v[i][2]<='9')){
                num=(v[i][1]-'0')*10+(v[i][2]-'0');
            }
            if(v[i].length()==2&&(v[i][1]>='0'&&v[i][1]<='9')){
                num=v[i][1]-'0';
            }
            switch(v[i][0]){
                case 'A':x-=num;break;
                case 'D':x+=num;break;
                case 'W':y+=num;break;
                case 'S':y-=num;break;
                default:break;
            }
        }
        cout << x << "," << y << endl;
    }
    return 0;
}

例3:识别有效IP地址和掩码并进行分类统计

题目描述:

请解析IP地址和对应的掩码,进行分类识别。要求按照A/B/C/D/E类地址归类,不合法的地址和掩码单独归类。 

所有的IP地址划分为 A,B,C,D,E五类 

A类地址1.0.0.0~126.255.255.255; 

B类地址128.0.0.0~191.255.255.255; 

C类地址192.0.0.0~223.255.255.255; 

D类地址224.0.0.0~239.255.255.255; 

E类地址240.0.0.0~255.255.255.255 

私网IP范围是: 

10.0.0.0~10.255.255.255 

172.16.0.0~172.31.255.255 

192.168.0.0~192.168.255.255 

子网掩码为前面是连续的1,然后全是0。(例如:255.255.255.32就是一个非法的掩码) 

本题暂时默认以0开头的IP地址是合法的,比如0.1.1.2,是合法地址

输入描述:

多行字符串。每行一个IP地址和掩码,用~隔开。

输出描述:

统计A、B、C、D、E、错误IP地址或错误掩码、私有IP的个数,之间以空格隔开。

示例1

输入

10.70.44.68~255.254.255.0
1.0.0.1~255.0.0.0
192.168.0.2~255.255.255.0
19..0.~255.255.255.0

输出

1 0 1 0 0 2 1

代码:

#include <iostream>
#include <vector>
#include <string>
#include <sstream>

using namespace std;

int stringtoint(string str){
    stringstream ss;
    int a;
    ss<<str;
    ss>>a;
    return a;
}

vector<int> toint(string str){
    string tmp;
    vector<int> res;
    int num;
    for(int i=0;i<str.length();i++){
        if(str[i]!='.'){
            tmp.push_back(str[i]);
        }
        else{
            num=stringtoint(tmp);
            tmp.clear();
            res.push_back(num);
        }
    }
    num=stringtoint(tmp);
    res.push_back(num);
    return res;
}

bool maskisvalid(vector<int> res){
    if(res.size()!=4){
        return false;
    }
    if(res[0]==255){
        if(res[1]==255){
            if(res[2]==255){
                if(res[3]==254||res[3]==252||res[3]==248||res[3]==240||res[3]==224||res[3]==192||res[3]==128||res[3]==0){
                    return true;
                }
                else{
                    return false;
                }
            }
            else{
                if(res[2]==254||res[2]==252||res[2]==248||res[2]==240||res[2]==224||res[2]==192||res[2]==128||res[2]==0){
                    if(res[3]==0){
                        return true;
                    }
                    else{
                        return false;
                    }
                }
            }
        }
        else{
            if(res[1]==254||res[1]==252||res[1]==248||res[1]==240||res[1]==224||res[1]==192||res[1]==128||res[1]==0){
                if(res[2]==0&&res[3]==0){
                    return true;
                }
                else{
                    return false;
                }
            }
        }   
    }
    else{
        if(res[0]==254||res[0]==252||res[0]==248||res[0]==240||res[0]==224||res[0]==192||res[0]==128){
            if(res[1]==0&&res[2]==0&&res[3]==0){
                return true;
            }
            else{
                false;
            }
        }
    }
    return false;
}

int main(){
    string str;
    int* res=new int[7];  //结果
    for(int i=0;i<7;i++){
            res[i]=0;
    }
    while(cin>>str){
        string ipstr,maskstr;
        vector<int> ip,mask;
        int i=0;
        for(;str[i]!='~';i++){
            ipstr.push_back(str[i]);   //得到ip字符串
        }
        i++;
        for(;i<str.length();i++){       
            maskstr.push_back(str[i]);    //得到mask字符串
        }
        ip=toint(ipstr);
        mask=toint(maskstr);
        if(maskisvalid(mask)){    //mask有效
            if((ip[1]>=0&&ip[1]<=255)&&(ip[2]>=0&&ip[2]<=255)&&(ip[3]>=0&&ip[3]<=255)){
                if(ip[0]>=1&&ip[0]<=126){   //A类
                    res[0]++;
                    if(ip[0]==10){
                        res[6]++;
                    }
                }
                else if(ip[0]>=128&&ip[0]<=191){   //B类
                    res[1]++;
                    if(ip[0]==172&&(ip[1]>=16&&ip[0]<=31)){
                        res[6]++;
                    }
                }
                else if(ip[0]>=192&&ip[0]<=223){   //C类
                    res[2]++;
                    if(ip[0]==192&&ip[1]==168){
                        res[6]++;
                    }
                }
                else if(ip[0]>=224&&ip[0]<=239){   //D类
                    res[3]++;
                }
                else if(ip[0]>=240&&ip[0]<=255){   //D类
                    res[4]++;
                }
            }  //ip[1]
        }//isvalid
        else{
                res[5]++;
        }
    }    //while
    cout << res[0] << " " << res[1] << " " << res[2] << " " << res[3] << " " << res[4] << " " << res[5] << " " << res[6] << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/linyuhan3232/article/details/89667971