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

1

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

思路:

①区间最大值,点更新。

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

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

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

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

③如何建树?

华为2016校园招聘上机笔试题_第1张图片

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

代码:

#include
#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(rx2){
                    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
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
map 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]b.y?1:0;
}
//并且sort和qsort刚好是相反的
//sort 真是由大到小,qsort假是由大到小
int main(){
    char a[1000];
    char b[100];
    set s;   //先添加进来,用于计数
    map 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::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=0;l--){
            if((p[i].x)[l]==' ') break;
        }
        if(l<=16) {
            cout<

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(BB[0])) {
                System.out.println(Array[0]);
            }else {
                System.out.println(Array[1]);
            }
        }
    }
}

你可能感兴趣的:(剑指Offer,数据结构)