2012最全华为上机试题及部分答案
2011年华为软件校园招聘编程测验
1、请上机编写程序,按题目要求提交文件。[详见考试说明,点击进入考试说明]
3、评卷通过在给定用例输入下,严格按照试题要求比较考生实现函数的输出与预设输出。两者相同则得分,不同则不得分。
4、评卷人保证测试用例输入参数的合法性,考生不用考虑输入参数非法或异常的情况
5、评卷人保证测试用例输入在被测函数正常合法情况下使用不会导致程序错误
6、如果考生函数异常导致程序崩溃或死循环,则自动评卷可能会被人为终止,剩余用例不被执行,无法得分
7、基于上述阅卷规则,请考生严格按照题目要求功能实现程序,尽量保证实现函数的稳健性,同时建议完成一道题并调试保证正确性后,再考虑并实现下一题目
1,判断电话号码是否合法:
//要注意情况包含,有可能会同时出现几种不好的情况,要按照顺序输出错误。不能同时输出好几种错误,应该是这样包含:先判断长度是否符合,再判断是否以86打头,再判断有无其他字符
int fun(char num[])
{ char *p=num;
int n=strlen(num);
if(n==13){
if(*p=='8'&&*(p+1)=='6')
while(*p!='\0'){
if(*p>='0'&&*p<='9')
p++;
else
return 2;
if(*p=='\0')
return 0;
}
else return 3;
}
else
return 1;
}
int main()
{
char num[]="87139a3887671";
int k=fun(num);
cout< return 0; } 1. 数组比较(20分) ?问题描述: 比较两个数组,要求从数组最后一个元素开始逐个元素向前比较,如果2个数组长度不等,则只比较较短长度数组个数元素。请编程实现上述比较,并返回比较中发现的不相等元素的 个数 比如:数组{1,3,5}和数组{77,21,1,3,5}按题述要求比较,不相等元素个数为0 数组{1,3,5}和数组{77,21,1,3,5,7}按题述要求比较,不相等元素个数为3 ?要求实现函数: int array_compare(int len1, int array1[], int len2, int array2[]) ?示例 1)输入:int array1[] = {1,3,5},int len1 = 3,int array2[] = {77,21,1,3,5},int len2 = 5 函数返回:0 2)输入:int array1[] = {1,3,5},int len1 = 3,int array2[] = {77,21,1,3,5,7},int len2 = 6 函数返回:3 函数如下: using namespace std; int f(int len1,int arry1[],int len2,int arry2[]) { int k=0; for(int i=len1-1,j=len2-1;i>=0&&j>=0;i--,j--) if(arry1[i]!=arry2[j]) k++; return k; } int main() { int num1[]={1,3,5}; int num2[]={77,21,1,3,5}; int k=f(3,num1,5,num2); cout< return 0; } 2. 约瑟夫问题 ?问题描述: 输入一个由随机数组成的数列(数列中每个数均是大于0的整数,长度已知),和初始计数值m。从数列首位置开始计数,计数到m后,将数列该位置数值替换计数值m,并将数列该位置数值出列,然后从下一位置从新开始计数,直到数列所有数值出列为止。如果计数到达数列尾段,则返回数列首位置继续计数。请编程实现上述计数过程,同时输出数值出列的顺比如:输入的随机数列为:3,1,2,4,初始计数值m=7,从数列首位置开始计数(数值3所在位置) 第一轮计数出列数字为2,计数值更新m=2,出列后数列为3,1,4,从数值4所在位置从新开始计数 第二轮计数出列数字为3,计数值更新m=3,出列后数列为1,4,从数值1所在位置开始计数第三轮计数出列数字为1,计数值更新m=1,出列后数列为4,从数值4所在位置开始计数 最后一轮计数出列数字为4,计数过程完成。 输出数值出列顺序为:2,3,1,4。 ?要求实现函数: void array_iterate(int len, int input_array[], int m, int output_array[ ]) 【输入】 int len:输入数列的长度; int intput_array[]:输入的初始数列 int m:初始计数值 【输出】 int output_array[]:输出的数值出列顺序 ?示例 输入:int input_array[] = {3,1,2,4},int len = 4,m=7 输出:output_array[] = {2,3,1,4} 函数如下: void fun(int len,int a1[],int len2,int a2[]) { int n=0,i=-1,k=1,m=len2; while(1){ for(int j=0;j i=(i+1)%len; //注意这个是%,不要写成/ if(a1[i]!=0) j++; } m=a1[i]; a2[n++]=a1[i]; a1[i]=0; if(k==len)break; k++; } } 3. 简单四则运算 ?问题描述: 输入一个只包含个位数字的简单四则运算表达式字符串,计算该表达式的值 注: 1、表达式只含+, -, *, / 四则运算符,不含括号 2、表达式数值只包含个位整数(0-9),且不会出现0作为除数的情况 3、要考虑加减乘除按通常四则运算规定的计算优先级 4、除法用整数除法,即仅保留除法运算结果的整数部分。比如8/3=2。输入表达式保证无0作为除数情况发生 5、输入字符串一定是符合题意合法的表达式,其中只包括数字字符和四则运算符字符,除此之外不含其它任何字符,不会出现计算溢出情况 ?要求实现函数: int calculate(int len,char *expStr) 【输入】 int len: 字符串长度; char *expStr: 表达式字符串; 【输出】无 【返回】计算结果 ?示例 1)输入:char *expStr = “1+4*5-8/3”函数返回:19 2)输入:char *expStr = “8/3*3”函数返回:6 简化版的四则运算:没有括号,只有加减乘除四种运算 int fun(char a[],int len) //字符数组和字符数组的长度 { int num[20]; char str[20]; int k1=0,k2=0; int data=0; for(int i=0;i { if(a[i]>='0'&&a[i]<='9') num[k1++]=a[i]-'0'; if(a[i]=='-'||a[i]=='+') str[k2++]=a[i]; if(a[i]=='*') {num[k1-1]=num[k1-1]*(a[i+1]-'0');i++;}//遇见*,就运算,结果保存在数组中 if(a[i]=='/') { num[k1-1]=num[k1-1]/(a[i+1]-'0');i++;} } int temp=num[0]; int j=0; //两个数组只剩下数组和加减运算符 while(j if(str[j]=='-') temp=temp-num[j+1]; else if(str[j]='+') temp=temp+num[j+1]; j++; } return temp; } int main() { har a[]="3*3+7+4/3"; int k=fun(a,9); cout< return 0; } 函数实现2:中序表达式转换为后序表达式,使用算法实现 int isp(char c) { int p; switch(c){ case'*': case'/':p=1;break; case'+': case'-': p=0;break; } return p; } char* transf(int len,char a[],char b[]) { int k=0; stack for(int i=0;i { if(a[i]>='0'&&a[i]<='9')b[k++]=a[i]; else { if(s1.empty())s1.push(a[i]); else while(isp(a[i])<=isp(s1.top())) {b[k++]=s1.top();s1.pop();} s1.push(a[i]); } } while(s1.empty()){ b[k++]=s1.top(); s1.pop(); } b[k]='\0'; return b; } void fun(char c,stack s2) { char p1,p2; if(!s2.empty()){ p1=s2.top();s2.pop(); else pos=false; cout<<"kongzhan"< if(!s2.empty()){ p2=s2.top();s2.top(); else pos=false; cout<<"kongzhan"< if(pos=true) switch(c){ case'+':s2.push(p1+p2);break; case'-':s2.push(p2-p1);break; case'*':s2.push(p1*p2);break; case'/':s2.push(p2/p1);break; } } void eval(char a[]) { stack for(int i=len;i switch(a[i]){ case'+': case'-': case'*': case'/':fun(a[i],&s2);break; default:s2.push(a[i]-'0');break; } } } int main() { char a[]="1+4*5-8/3"; int len=strlen(a); char b[20]; char *q=transf(9,a,b); cout< return 0; } 第五题:一副牌中发五张扑克牌给你:让你判断数字的组成:有以下几种情况:1:四条:即四张一样数值的牌(牌均不论花色) 2:三条带一对 3:三条带两张不相同数值的牌 4:两对 5:顺子包括10,J,Q,K,A 6:什么都不是 7:只有一对 思路:将数组排序,统计相同的数字的个数,再分情况讨论 void sort(int a[]) { int temp; for(int i=0;i<5;i++) for(int j=0;j<5;j++) if(a[i]>a[j]) {temp=a[i];a[i]=a[j];a[j]=temp;} } //修改的排序 void sort(int a[]) { int temp; for(int i=0;i<5;i++) for(int j=i+1;j<5;j++) if(a[i]>a[j]) {temp=a[i];a[i]=a[j];a[j]=temp;} } void test(int a[]) { int *b=new int[5]; int k=1; for(int i=0;i<5;i++) { b[i]=a[i];} for(int j=0;j<4;j++) if(a[j]==a[j+1]) k++; if(k==4){ if(b[1]==b[3]) cout<<"四条"< else cout<<"三条带一对"< } if(k==3){ if(b[1]!=b[2]||b[2]!=b[3]) cout<<"三条带两个不同的牌"< else cout<<"两对"< } if(k==2) cout<<"一对"< if(k==1){ if(b[4]-b[0]==4&&b[4]-b[1]==3&&b[4]-b[2]==2&&b[4]-b[3]==1) cout<<"顺子< else cout<<"什么都不是"< } } int main() { int a[]={1,2,4,4,4}; test(a); return 0;} 第二题:求两个数组的和差就是去掉两个数组中相同的元素然后将两个数组中的元素存放在一个新的数组中,按大小顺序排序 思路:将数组A和数组B分别进行排序,然后将A与B进行比较,重复的跳过去,不重复的赋给数组C,依次输出。 while(i < la && j < lb) { if(aa[i] < bb[j]) { c[sub] = aa[i]; ++sub; ++i; } else if(aa[i] > bb[j]) { c[sub] = bb[j]; ++sub; ++j; } else if(aa[i] == bb[j]) { ++i; ++j; } } for(; i < la; ++i) {c[sub] = aa[i]; ++sub; } for(; j < lb; ++j) {c[sub] = bb[j]; ++sub; } 四:逆序单链表 node *reverse(node *head) { node *p1,*p2,*p3; p1=head; p2=head->next; while(p2){ p3=p2->next; p2->next=p1; p1=p2; p2=p3; } head->next=NULL; head=p1; return head; } 2. 将一个字符串的元音字母复制到另一个字符串,并排序(30分) 问题描述:有一字符串,里面可能包含英文字母(大写、小写)、数字、特殊字符,现在需要实现一函数,将此字符串中的元音字母挑选出来,存入另一个字符串中,并对字符串中的字母进行从小到大的排序(小写的元音字母在前,大写的元音字母在后,依次有序)。 说明:1、元音字母是a,e,i,o,u,A,E,I,O,U。 2、筛选出来的元音字母,不需要剔重;最终输出的字符串,小写元音字母排在前面,大写元音字母排在后面,依次有序。 要求实现函数:void sortVowel (char* input, char* output); using namespace std; void fun(char a[],char s[]) //提取元音字母,放入数组 { int i=0,n=0; while(a[i]!='\0'){ if(a[i]=='a'||a[i]=='e'||a[i]=='i'||a[i]=='o'||a[i]=='u') s[n++]=a[i]; else if (a[i]=='A'||a[i]=='E'||a[i]=='I'||a[i]=='O'||a[i]=='U') s[n++]=a[i]; i++; } char temp; //将数组排序 for(int i=0;i for(int j=0;j if(s[j]>s[j+1]) {temp=s[j];s[j]=s[j+1];s[j+1]=temp;} int k=0; //定位大写字母的最后位置 while(s[k]>='A'&&s[k]<='Z'){ k++; } for(int j=0;j cout< char *p=new char[20]; //将字符串变换位置,输出。 char *q=p; for(int i=k;i {*p=s[i];p++;} for(int j=0;j {*p=s[j];p++;} *p='\0'; cout< } int main() { char str[]="HaJsdStOoAOeINaPQaWEiAIiO"; char s[20]; fun(str,s); return 0; } 3. 身份证号码合法性判断 我国公民的身份证号码特点如下: 1、长度为18位; 2、第1~17位只能为数字; 3、第18位可以是数字或者小写英文字母x。 4、身份证号码的第7~14位表示持有人生日的年、月、日信息。 例如:511002 19880808 0111或511002 198********x。 请实现身份证号码合法性判断的函数。除满足以上要求外,需要对持有人生日的年、月、日信息进行校验。年份大于等于1900年,小于等于2100年。需要考虑闰年、大小月的情况。所谓闰年,能被4整除且不能被100整除或能被400整除的年份,闰年的2月份为29天,非闰年的2月份为28天。其他情况的合法性校验,考生不用考虑。 函数返回值: 1)如果身份证号合法,返回0; 2)如果身份证号长度不合法,返回1; 3)如果身份证号第1~17位含有非数字的字符,返回2; 4)如果身份证号第18位既不是数字也不是英文小写字母x,返回3; 5)如果身份证号的年信息非法,返回4; 6)如果身份证号的月信息非法,返回5; 7)如果身份证号的日信息非法,返回6(请注意闰年的情况); 要求实现函数: int verifyIDCard(char* input) 示例 1)输入:”511002 111222”,函数返回值:1; 2)输入:”511002 abc123456789”,函数返回值:2; 3)输入:”511002 198********a”,函数返回值:3; 4)输入:”511002 188808081234”,函数返回值:4; 5)输入:”511002 198813081234”,函数返回值:5; 6)输入:”511002 198808321234”,函数返回值:6; 7)输入:”511002 1989 0229 1234”,函数返回值:7; 8)输入:”511002 198808081234”,函数返回值:0; i nt fun(char *str) { int year=0,month=0,day=0; if((strlen(str)-1)<18) //1 { for(int i=0;i<18;i++) { if(str[i]>='0'&&str[i]<='9') //2 ; else return 2; } if(str[17]=='x'||(str[17]>='0'&&str[17]<='9'))//3 {for(int i=6;i<10;i++) year=year*10+str[i]-'0'; if(year>1900&&year<2100)//4 { for(int i=10;i<12;i++) month=month*10+str[i]-'0'; if(month>0&&month<=12)//5 { for(int i=12;i<14;i++) day=day*10+str[i]-'0'; if(day<=31)//6 { if(year%4!=0&&month==2&&day<=28) return 0; else if(year%4==0&&month==2&&day<29) return 0; else if(year%4!=4&&month!=2&&day<31) return 0; else return 6; } else return 6; } else return 5; } else return 4; } else return 3; } else return 1; } int main() { char a[]="340621198608377817"; int k=fun(a); cout< return 0; } 第二题:比较一个数组的元素是否为回文数组 判断是否是回文数组: bool fun(char a[]) { int n=strlen(a); int i=0,j=n-1; while(i if(a[i]!=a[j]) return false; i++;j--; } return true; } 第三题:求两个数组的和差:就是去掉两个数组中相同的元素然后将两个数组中的元素存放在一个新的数组中且数组A中元素要在B数组元素之前 思路:利用循环比较,将相同的数字的标记为0,再赋给数组C int main() { int a[]={1,3,5,7,9,12,13}; int s[]={1,3,5,6,7,8,9}; int len1=sizeof(a)/sizeof(int); int len2=sizeof(s)/sizeof(int); for(int i=0;i for(int j=0;j if(a[i]==s[j]) {a[i]=0;s[j]=0;} int t[30]; int k=0,i=0,j=0; while(i if(a[i]!=0) t[k++]=a[i]; i++; } while(j if(s[j]!=0) t[k++]=s[j]; j++; } for(int i=0;i cout< return 0; } 字符串计算 1、选秀节目打分,分为专家评委和大众评委,score[] 数组里面存储每个评委打的分数,judge_type[] 里存储与score[] 数组对应的评委类别,judge_type == 1,表示专家评委,judge_type == 2,表示大众评委,n表示评委总数。打分规则如下:专家评委和大众评委的分数先分别取一个平均分(平均分取整),然后,总分= 专家评委平均分* 0.6 + 大众评委* 0.4,总分取整。如果没有大众评委,则总分= 专家评委平均分,总分取整。函数最终返回选手得分。 int cal_score(int score[], int judge_type[], int n) { int sum1=0,sum2=0,avg1=0,avg2=0; int m=0,k=0; for(int i=0;i if(judge_type[i]==1) {sum1=sum1+score[i];m++;} if(judge_type[i]==2) {sum2=sum2+score[i];k++;} } avg1=sum1/m;avg2=sum2/k; return (int)(avg1*0.6+avg2*0.4); } int main() { int input[]={3,6,1,9,7,8}; int output[]={1,1,2,1,2,2}; int n=sizeof(input)/sizeof(int); int p=cal_score(input,output,n); cout< return 0; } 2、给定一个数组input[] ,如果数组长度n为奇数,则将数组中最大的元素放到output[] 数组最中间的位置,如果数组长度n为偶数,则将数组中最大的元素放到output[] 数组中间两个位置偏右的那个位置上,然后再按从大到小的顺序,依次在第一个位置的两边,按照一左一右的顺序,依次存放剩下的数。 例如:input[] = {3, 6, 1, 9, 7} output[] = {3, 7, 9, 6, 1}; input[] = {3, 6, 1, 9, 7, 8} output[] = {1, 6, 8, 9, 7, 3} 函数接口void sort(int input[[, int n, int output[]) using namespace std; void sort(int input[],int n,int output[]) { int i=0,j=n-1; int temp; for(int i=0;i for(int j=0;j { if(input[j]>input[j+1]) {temp=input[j];input[j]=input[j+1];input[j+1]=temp;} } int k=0; i=0;j=n-1; if(0==n%2) { while(i { output[i++]=input[k++]; output[j--]=input[k++]; } } if(1==n%2) { while(i { output[j--]=input[k++]; output[i++]=input[k++]; } output[(n-1)/2]=input[k]; //cout< } for(int j=0;j cout<