2014华为机试真题(1)
1.及格线问题
10个学生考完期末考试评卷完成后,A老师需要划出及格线,要求如下:
(1) 及格线是10的倍数;
(2) 保证至少有60%的学生及格;
(3) 如果所有的学生都高于60分,则及格线为60分
#include<iostream> using namespace std; /**********************solution1************************************/ int cmp(const void *a,const void *b) { return *(int*)a-*(int*)b; } template<unsigned int N,typename T> int process1(T (&data)[N]){ qsort(data,N,sizeof(T),cmp); if(data[0]>=60) return 60; else return data[4]/10*10; } /**********************solution2************************************/ template<unsigned int N,typename T> int process2(T(&data)[N]){ int* count=new int[11]; memset(count,0,11*sizeof(int)); for(int i=0;i<N;i++) count[data[i]/10]++; if(count[10]==10) return 10; else if(count[10]>=6) return 100; for(int i=9;i>=0;i--){ count[i]+=count[i+1]; if(i>=6&&count[i]==10) return 60; else if(count[i]>=6) return i*10; } delete []count; } int main(int argc, char *argv[]) { int a[]={100,100,100,100,100,43,30,20,41,42}; printf("%d\n",process2(a)); }
solution1使用了快速排序库函数。其中包含自定义比较函数cmp。对于浮点型,一定要使用三目运算符。其中的qsort函数包含在<stdlib.h>的头文件里,strcmp包含在<string.h>的头文件里。这里总结如下,对于从小到大排序:
int num[100]; int cmp ( const void *a , const void *b )//int { return *(int *)a - *(int *)b; } qsort(num,100,sizeof(num[0]),cmp); char word[100]; int cmp( const void *a , const void *b )//char { return *(char *)a - *(int *)b; } qsort(word,100,sizeof(word[0]),cmp); double in[100]; int cmp( const void *a , const void *b )//double { return *(double *)a > *(double *)b ? 1 : -1; } qsort(in,100,sizeof(in[0]),cmp); struct In { double data; int other; }s[100] int cmp( const void *a ,const void *b)//结构体一级 { return ((In *)a)->data > ((In *)b)->data ? 1 : -1; } qsort(s,100,sizeof(s[0]),cmp); struct In { int x; int y; }s[100]; int cmp( const void *a , const void *b )//结构体二级 { In *c = (In *)a; In *d = (In *)b; if(c->x != d->x) return c->x - d->x; else return d->y - c->y; } qsort(s,100,sizeof(s[0]),cmp); struct In { int data; char str[100]; }s[100]; int cmp ( const void *a , const void *b )//结构体按字符串排序 { return strcmp( ((In *)a)->str , ((In *)b)->str ); } qsort(s,100,sizeof(s[0]),cmp);
2.亮灯的数目
一条长廊里依次装有n(1≤n≤65535)盏电灯,从头到尾编号1、2、3、…n-1、n。每盏电灯由一个拉线开关控制。开始,电灯全部关着。
有n个学生从长廊穿过。第一个学生把号码凡是1的倍数的电灯的开关拉一下;接着第二个学生把号码凡是2的倍数的电灯的开关拉一下;接着第三个学生把号码凡是3的倍数的电灯的开关拉一下;如此继续下去,最后第n个学生把号码凡是n的倍数的电灯的开关拉一下。n个学生按此规定走完后,长廊里电灯有几盏亮着。
注:电灯数和学生数一致。不能写笨拙的双重循环(优化过的是可以的),会运行超时。本题有运行时间限制(一说10000ms)。
输入 65535 输出 255
基本思路:
对于任何一盏灯,由于它原来不亮,那么当它的开关被按奇数次时,灯是开着的;当它的开关被按偶数次时,灯是关着的;一盏灯的开关被按的次数,恰等于这盏灯的编号的因数的个数;要求哪些灯还亮着,就是问哪些灯的编号的因数有奇数个.显然完全平方数有奇数个因数。每个数除以一个数A等于另一个数B,那么A和B都是它的因数,于是因数是成对出现的,但是要因数是奇数,就必须A=B所以这个数就必须是一个是的平方得到的。
综上所述这道题非常简单,就是找1-65535中完全平方数的个数。
int main(int argc, char *argv[]) { int n; while(~scanf("%d",&n)){ int ans=0; for(int i=1;;++i) { if(i*i>n) break; ++ans; } printf("%d\n",ans); } return 0; }
3.计算最大值最小值之外的个数
int count(){ int temp; cin>>temp; int max=temp,min=temp; int i=1,j=1,k=1; char c; cin>>c; while(c!='\n'){ cin>>temp; k++; if(temp<min){ min=temp; i=1; } else if(temp==min) i++; else if(temp==max) j++; else if(temp>max){ max=temp; j=1; } scanf("%c",&c);//c=getchar() } if(k==1||min==max) return 0; else return k-i-j; }scanf和getchar函数都可以读取空白符。
4.括号的匹配问题
输入一串字符串,其中有普通的字符与括号组成(包括‘(’、‘)’、‘[’,']'),要求验证括号是否匹配,如果匹配则输出0、否则输出1.
Smpleinput:dfa(sdf)df[dfds(dfd)] Smple outPut:0
int match(){ stack<char> s; char p; scanf("%c",&p); while(p!='\n'){ if(p=='('||p=='[') s.push(p); else if(p==')'){ if(!s.empty()&&s.top()=='(') s.pop(); else return 1; } else if(p==']'){ if(!s.empty()&&s.top()=='[') s.pop(); else return 1; } scanf("%c",&p); } if(s.empty()) return 0; else return 1; }
5.判断是否为回文数
int decision(){ int n,m=0; cin>>n; int temp=n; while(temp){ m*=10; m+=(temp%10); temp/=10; } if(m==n) return 1; else return 0; }本质上,即计算该数的逆序数,比较该逆序数是否和原来的数相等
6.翻译英文数字
例如:
输入:OneTwoThree
输出:123
输入:OneTwoDoubleTwo
输出:1222
输入:1Two2
输出:ERROR
输入:DoubleDoubleTwo
输出:ERROR
有空格,非法字符,两个Double相连,Double位于最后一个单词 都错误。
const string process(const string& s){ const char* num[]={"zero","one","two","three","four","five","six","seven","eight","nine"}; if(s.empty()) return "error"; int i=0; bool flagDouble=false; bool flagNumber; string result; while(i<s.length()){ flagNumber=false; if(isalpha(s[i])){//先判断是否是字母 for(int j=0;j<10;j++){//判断数字 if((i+strlen(num[j])-1)<s.length()&&!strcmp(s.substr(i,strlen(num[j])).c_str(),num[j])){ result+=(char)(j+'0'); i+=strlen(num[j]); if(flagDouble){//该数字是否需要重复 result+=(char)(j+'0'); flagDouble=false; } flagNumber=true;//数字判断成功 break; } } if(!flagNumber&&(i+5)<s.length()&&!strcmp(s.substr(i,6).c_str(),"double")){//判断double if(!flagDouble){ flagDouble=true; i+=6; } else//double之前已经出现过 return "error"; } if(!flagNumber&&!flagDouble)//double和数字都未判读成功 return "error"; } else return "error";//非字母 } if(flagDouble)//防止,double与数字没有匹配,即单个double出现 return "error"; else return result; } int main(int argc, char *argv[]) { string s; getline(cin,s); cout<<process(s)<<endl; }
7.不重复逆序输出整数
输入一个整数,如12336544,或1750,然后从最后一位开始倒过来输出,最后如果是0,则不输出,输出的数字是不带重复数字的,所以上面的输出是456321和571。如果是负数,比如输入-175,输出-571。
int reverseNum(int num){ int* flag=new int[10]; int result=0; int plus=true; memset(flag,0,10*sizeof(int)); if(num<0){ num=abs(num); plus=false; } while(!(num%10)) num/=10; int temp; while(num){ temp=num%10; if(!flag[temp]){ result*=10; result+=temp; flag[temp]+=1; } num/=10; } if(!plus) return -1*result; else return result; } int main(int argc, char *argv[]) { cout<<reverseNum(-12336544)<<endl; }
8.模拟减法运算
输入两行字符串正整数,第一行是被减数,第二行是减数,输出第一行减去第二行的结果。
备注:1、两个整数都是正整数,被减数大于减数
示例:
输入:1000000000000001
1
输出:1000000000000000
注意大数用char a[]存储,用%s接收,一位一位的运算。注意a[0]里的正负号
const char* sub(const string& num1,const string& num2){ if(num1.empty()||num2.empty()) return NULL; int temp; int add=0; int size1=num1.length(); int size2=num2.length(); char* result=new char[size1+1]; memset(result,'\0',size1+1); int i; for(i=0;i<size2;i++){ temp=num1[size1-i-1]-num2[size2-i-1]-add; add=0; if(temp<0){ temp+=10; add=1; } result[size1-i-1]=temp+'0'; } if(size1>size2) result[size1-i-1]=num1[size1-i-1]-add; for(i=0;i<(size1-size2-1);i++) result[i]=num1[i]; //删除空白部分 i=0; while(result[i]=='0')//开头存在0的情况 i++; strcpy(result,result+i); return result; } int main(int argc, char *argv[]) { string num1,num2; getline(cin,num1); getline(cin,num2); cout<<sub(num1,num2)<<endl; }