华为2016校园招聘上机笔试题

1

老师想知道从某某同学当中,分数最高的是多少,现在请你编程模拟老师的询问。当然,老师有时候需要更新某位同学的成绩.

思路:

①区间最大值,点更新。

这里是最简单的,其实还有区间求和,区间最大值,区间最小值,点更新,区间更新。

可以用线段树、树状数组、RMQ

①这里只简单说明一下区间最大值和点更新,剩余的放在下一个篇详细介绍。

②就用线段树吧,n个数据,就是n个叶子节点存放数据。父节点表示范围的最大值,每次修改之后需要向上更新。

③如何建树?

线段树,build(1,1,n)递归建树,当节点的l==r的时候,递归结束,叶子节点(这里的l和r不是左右子树而是左右覆盖范围),依次得到的叶子节点肯定是从左到右的(8-->9-->5-->6-->7)。l和r可以表示输入数据的下标,就是覆盖范围嘛。更新点的值比更新区间的值要简单,查到点只需要向上更新即可。

代码:

#include<stdio.h>
#define N 30005
struct node{
    int l;     //节点左覆盖范围
    int r;     //节点右覆盖范围
    int value;   //覆盖范围的最大值
}p[N*2];
int a[N];      //输入数据
int max(int a,int b){
    return a>b?a:b;
}
void build(int o,int l,int r){
    p[o].l=l;
    p[o].r=r;
    if(l==r) {  //叶子节点
        p[o].value=a[l];
        return;
    }
    int mid=(l+r)/2;
    build(o*2,l,mid);
    build(o*2+1,mid+1,r);
    p[o].value=max(p[o*2].value,p[o*2+1].value);
}
//从根节点开始查
int Find(int o,int l,int r){
    if(p[o].l==l&&p[o].r==r){
        return p[o].value;
    }
    //左儿子的右覆盖范围   小于  l   (在右子树)
    if(l>p[o*2].r) return Find(o*2+1,l,r);
    //右儿子的左覆盖范围   大于  r   (在左子树)
    else if(r<p[o*2+1].l) return  Find(o*2,l,r);
    //横跨左右子树
    else return max(Find(o*2,l,p[o*2].r),Find(o*2+1,p[o*2+1].l,r));
}
//更新点的值,需要向上更新父亲节的值
void update(int o,int index,int x){
    if(p[o].l==p[o].r){    //查找,当l==r时,index==r==l
        p[o].value=x;
        return;           //一定要要结束递归
    }
    if(index<=p[o*2].r) update(o*2,index,x);
    else update(o*2+1,index,x);
    p[o].value=max(p[o*2].value,p[o*2+1].value);
}
int main(){
    int n,m,x1,x2;
    char str[5];
    while(~scanf("%d%d",&n,&m)){
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        build(1,1,n);
        while(m--){
            scanf("%s%d%d",str,&x1,&x2);
            if(str[0]=='Q'){
                if(x1>x2){
                    int xx=x1;
                    x1=x2;
                    x2=xx;
                }
                printf("%d\n",Find(1,x1,x2));
            }else{
                update(1,x1,x2);
            }
        }
    }
    return 0;
}

2

开发一个简单错误记录功能小模块,能够记录出错的代码所在的文件名称和行号。 
处理:
1.记录最多8条错误记录,对相同的错误记录(即文件名称和行号完全匹配)只记录一条,错误计数增加;(文件所在的目录不同,文件名和行号相同也要合并)
2.超过16个字符的文件名称,只记录文件的最后有效16个字符;(如果文件名不同,而只是文件名的后16个字符和行号相同,也不要合并)
3.输入的文件可能带路径,记录文件名称不能带路径

思路

①首先字符串处理,有一个转义符误区,得到文件名和行数。然后定义一个map就行相同文件名和行数进行统计,map插入会改变输入顺序,这是第二个误区,需要一个辅助记录输入顺序。最后map转化结构题数组,进行结构体排序。

②结构体排序可以用sort和qsort,但是在本案例中qsort不能通过,我也不知什么个情况,注意cmp函数的返回会值(二者不同),已及决定升降序排序(刚好相反)。

③第一次提交答案错误,给出输出是中间是空格,其实不是,就是一个一行(坑了好久)。

代码

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<stdlib.h>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
using namespace std;
map<string,int> flag;
int counts=0;
struct node{
    string x;
    int y;
};
//qsort,返回值1和-1代表真假
/*int cmp(const void *a,const void *b){
   if((*(struct node *)a).y==(*(struct node *)b).y){
        return flag[(*(struct node *)a).x]>flag[(*(struct node *)b).x];
    }
    return (*(struct node *)a).y > (*(struct node *)b).y ? -1 : 1;
}*/
//sort返回值1和0代表真假
int cmp(const node &a,const node &b){
    if(a.y==b.y) return flag[a.x]<flag[b.x]?1:0;
    return a.y>b.y?1:0;
}
//并且sort和qsort刚好是相反的
//sort 真是由大到小,qsort假是由大到小
int main(){
    char a[1000];
    char b[100];
    set<string> s;   //先添加进来,用于计数
    map<string,int> ans;
    while(scanf("%s%s",a,b)!=EOF){
        int len=strlen(a);
        int i=len-1;
        for(;i>=0;i--)
            if(a[i]=='\\') break;   //多加一个反斜杠转义符
        string save;                //文件名_行数
        for(i++;i<len;i++){
            save+=a[i];
        }
        save+=" ";
        save+=b;
        if(s.find(save)!=s.end()){
            ans[save]=ans[save]+1;
        }else{   //首次插入
            //map插入会乱序,需要一个辅助flag,记录输入顺序
            flag[save]=counts++;
            s.insert(save);
            ans[save]=1;
        }
    }
    struct node p[counts];
    int j=0;
    map<string,int>::iterator it;
    for(it=ans.begin();it!=ans.end();it++){
        p[j].x=it->first;
        p[j++].y=it->second;
    }
    sort(p,p+counts,cmp);    // qsort(p, counts, sizeof(p[0]),cmp);
    int num=0;
    for(int i=0;i<counts;i++){
        //统计文件名是否超16
        int len=(p[i].x).length();
        int l;
        for(l=len-1;l>=0;l--){
            if((p[i].x)[l]==' ') break;
        }
        if(l<=16) {
            cout<<p[i].x;
        }else{
            string q;
            for(int ll=l-16;ll<len;ll++)
                q+=(p[i].x)[ll];
            cout<<q;
        }
        cout<<" "<<p[i].y<<endl;
        num++;
        if(num==8) break;
    }
    return 0;
}

3

扑克牌游戏大家应该都比较熟悉了,一副牌由54张组成,含3~A,2各4张,小王1张,大王1张。牌面从小到大用如下字符和字符串表示(其中,小写joker表示小王,大写JOKER表示大王):) 
3 4 5 6 7 8 9 10 J Q K A 2 joker JOKER 
输入两手牌,两手牌之间用“-”连接,每手牌的每张牌以空格分隔,“-”两边没有空格,如:4 4 4 4-joker JOKER
请比较两手牌大小,输出较大的牌,如果不存在比较关系则输出ERROR

基本规则:
(1)输入每手牌可能是个子,对子,顺子(连续5张),三个,炸弹(四个)和对王中的一种,不存在其他情况,由输入保证两手牌都是合法的,顺子已经从小到大排列;
(2)除了炸弹和对王可以和所有牌比较之外,其他类型的牌只能跟相同类型的存在比较关系(如,对子跟对子比较,三个跟三个比较),不考虑拆牌情况(如:将对子拆分成个子)
(3)大小规则跟大家平时了解的常见规则相同,个子,对子,三个比较牌面大小;顺子比较最小牌大小;炸弹大于前面所有的牌,炸弹之间比较牌面大小;对王是最大的牌;
(4)输入的两手牌不会出现相等的情况。

答案提示:
(1)除了炸弹和对王之外,其他必须同类型比较。
(2)输入已经保证合法性,不用检查输入是否是合法的牌。
(3)输入的顺子已经经过从小到大排序,因此不用再排序了.

思路

①首先明确告诉你,出的牌必须合法,单个,对子,顺子,三个,炸弹

②以上五种情况进行排列组合,要么有一方赢,要么组合错误(如单个--对子)

③一种情况是牌数相同,只需要比较第一位即可(不会相等,顺子排好序了)

在一副牌中,都为1的时候是单个,都为2的时候是对子,都为三的时候是三个,都为4的时候是炸弹,都大于等于5的时候是顺子。

④一种情况是牌数不等,一方是炸弹(两种类型,王砸和其它炸),要不然是ERROR。

注意:比如长度是4,那么一定是炸弹(只有炸弹才一次出4张),比如长度是2,要么是对子,要么是王炸。

代码

public class Main {
    public static void main(String[] args) {  
        Scanner cin=new Scanner(System.in);
        String str=cin.nextLine();
        String[] Array=str.split("-");
        String[] A=Array[0].split(" ");
        String[] B=Array[1].split(" ");
        int[] AA=new int[A.length];
        int[] BB=new int[B.length];
        for(int i=0;i<A.length;i++) {
            //3 4 5 6 7 8 9 10 J Q K A 2 joker JOKER
            if(A[i].equals("3")) {
                AA[i]=3;
            }else if(A[i].equals("4")) {
                AA[i]=4;
            }else if(A[i].equals("5")) {
                AA[i]=5;
            }else if(A[i].equals("6")) {
                AA[i]=6;
            }else if(A[i].equals("7")) {
                AA[i]=7;
            }else if(A[i].equals("8")) {
                AA[i]=8;
            }else if(A[i].equals("9")) {
                AA[i]=9;
            }else if(A[i].equals("10")) {
                AA[i]=10;
            }else if(A[i].equals("J")) {
                AA[i]=11;
            }else if(A[i].equals("Q")) {
                AA[i]=12;
            }else if(A[i].equals("K")) {
                AA[i]=13;
            }else if(A[i].equals("A")) {
                AA[i]=14;
            }else if(A[i].equals("2")) {
                AA[i]=15;
            }else if(A[i].equals("joker")) {
                AA[i]=16;
            }else if(A[i].equals("JOKER")) {
                AA[i]=17;
            }
        }
        for(int i=0;i<B.length;i++) {
            //3 4 5 6 7 8 9 10 J Q K A 2 joker JOKER
            if(B[i].equals("3")) {
                BB[i]=3;
            }else if(B[i].equals("4")) {
                BB[i]=4;
            }else if(B[i].equals("5")) {
                BB[i]=5;
            }else if(B[i].equals("6")) {
                BB[i]=6;
            }else if(B[i].equals("7")) {
                BB[i]=7;
            }else if(B[i].equals("8")) {
                BB[i]=8;
            }else if(B[i].equals("9")) {
                BB[i]=9;
            }else if(B[i].equals("10")) {
                BB[i]=10;
            }else if(B[i].equals("J")) {
                BB[i]=11;
            }else if(B[i].equals("Q")) {
                BB[i]=12;
            }else if(B[i].equals("K")) {
                BB[i]=13;
            }else if(B[i].equals("A")) {
                BB[i]=14;
            }else if(B[i].equals("2")) {
                BB[i]=15;
            }else if(B[i].equals("joker")) {
                BB[i]=16;
            }else if(B[i].equals("JOKER")) {
                BB[i]=17;
            }
        }
        if(A.length!=B.length) {//不等
            //一个其它的和一个炸弹
            //一个炸弹和一个王炸
            if(A.length==2&&AA[0]==16) {
                System.out.println(Array[0]);
            }else if(B.length==2&&BB[0]==16) {
                System.out.println(Array[1]);
            }else if(A.length==4) {
                System.out.println(Array[0]);
            }else if(A.length==4) {
                System.out.println(Array[1]);
            }else {
                System.out.println("ERROR");
            }
        }else {  //相等
            if(AA[0]>(BB[0])) {
                System.out.println(Array[0]);
            }else {
                System.out.println(Array[1]);
            }
        }
    }
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值