攻城狮凌风

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;
}









posted on 2015-08-10 22:57  攻城狮凌风  阅读(384)  评论(0编辑  收藏  举报

导航