华为往年机试题目(三)

一、

#include<iostream>
#include<stack>
#include<string>
using namespace std;
 int reverse(int x) {
      int a = 0;
      do {
        a = a * 10 + (x % 10);
        x /= 10;
      } while(x > 0);
      return a;
    }

    int reverseAdd(int a, int b) {
      if (a < 1 || a > 70000 || b < 1 || b > 70000) {
        return -1;
      }
      return reverse(a) + reverse(b);
    }

    #include "stdio.h"
    int main() {
      int a, b;
      scanf("%d,%d", &a, &b);
      printf("%d\n", reverseAdd(a, b));
      return 0;
    }

#include<iostream>
#include<stack>
#include<string>
using namespace std;
int Rever(int x)
{
	int y=0;
	for(;x>0;)
	{
		y=y*10+x%10;
		x=x/10;
	}
	return y;
}

int main()
{
	int a,b;
	cin>>a;
	cin>>b;
	int c;
	c=Rever(a)+Rever(b);
	cout<<c;
	return 0;
}

二、

搞清楚每次变化导致的位置变化即可,考察多次的条件判断。

三、

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const int inf = 0x7f7f7f7f;
int d[50];
int a[][7] =
{
    {0},
    {0, 0, 2, 10, 5, 3, -1},
    {0, -1, 0, 12, -1, -1, 10},
    {0, -1, -1, 0, -1, 7, -1},
    {0, 2, -1, -1, 0, 2, -1},
    {0, 4, -1, -1, 1, 0, -1},
    {0, 3, -1, 1, 0, 2, 0}
};//时间花费矩阵 
int x, y;//目的地,大雾城市 
int res;
int used[10];//是否标记 
int ans = inf;
int ansp;
int ansd[50];
    
void dfs(int now, int cost, int p)//5 0 1 ,出发地,花费时间,路径个数 
{
    if (now == x)  //到达目的地 
	{
        if (cost < ans) //花费少了就更改新的路径
		{
          ans = cost;
          for (int i = 0; i < p; i++) 
		  {
            ansd[i] = d[i];//走过的路
          }
          ansp = p;//路个数
        }
        return;//结束标志 
    }
    for (int i = 1; i <= 6; i++) 
	{
        if (i == y) //大雾城市 
		{
          continue;//时间为无线大,回到循环 
        }
        if (used[i] == 0 && a[now][i] >= 0) //没走过,并且能通 
		{
          used[i] = 1;//标记 走过 
          d[p] = i;//记录走过的路 
          dfs(i, cost + a[now][i], p + 1);//递归 
          used[i] = 0;//标记撤销 
        }
    }
}



int main()
{
    static char emp[] = "";
    static char col[] = ", ";
    scanf("%d%d", &x, &y);//出差城市,大雾城市 
    
    if (x == 5) 
	{
        printf("0\n[]\n");
        return 0;//出差为5的话,0不可达 
    } 
    if (y == 5) 
	{
        printf("1000\n[]\n");
        return 0;//大雾为5的话,1000不可达 
    }
    
	d[0] = 5;
    used[5] = 1;
    
    dfs(5, 0, 1);//核心算法 
    
    char *p = emp;
    if (ans == inf) 
	{
        printf("1000\n[]\n");
    } 
	else 
	{
        printf("%d\n[", ans);
        for (int i = 0; i < ansp; i++) 
		{
          printf("%s%d", p, ansd[i]);
          p = col;
        }
        printf("]\n");
      }
    }

深度优先搜索的问题,难度有点大~  

四、

题目描述

请设计一个算法完成两个超长正整数的加法。

输入描述:

输入两个字符串数字

输出描述:

输出相加后的结果,string型

#include<iostream>
#include<string> 
#include<cmath>
#include<algorithm>
using namespace std;

int main()
{
	//string a="9999999999999",b="99";
	string a,b;
	cin>>a;
	cin>>b;
	
	int n1=a.length(),n2=b.length();
	string x,y;
	for(int i=0;i<n1;i++)
	{
	    x[i]=a[n1-i-1];
	}  
	for(int i=0;i<n2;i++)
	{
	    y[i]=b[n2-i-1];
	}
	
	if(n1<n2)
    {
    	for(int i=n1;i<n2;i++)
		    x[i]='0'; 
	}
	else
	{
		for(int i=n2;i<n1;i++)
		    y[i]='0'; 
	}
	
	int n=max(n1,n2);
    int s[100];
    int f=0;
    for(int i=0;i<n;i++)
    {
    	int c=x[i]-48+y[i]-48+f;
    	if(c<10)
    	{
    		s[i]=c;
    		f=0;
		}
		else
		{
			s[i]=c-10;
			f=1;
		}	    
	}
	if(f==1)
	{
		s[n]=1;
	    n=n+1;
	}
	for(int j=0;j<n;j++)
	    cout<<s[n-1-j];
	cout<<endl;

	string r[100];
	for(int j=0;j<n;j++)
	{
	    r[j]=s[n-1-j]+'0';
    }
    for(int j=0;j<n;j++)
        cout<<r[j];
	return 0;		
}

#include<iostream>
#include<string> 
#include<cmath>
#include<algorithm>
using namespace std;

int main()
{
	//string a="9999999999999",b="99";
	string a,b;
	cin>>a;
	cin>>b;
	
	int n1=a.length(),n2=b.length();
	string x,y;
	for(int i=0;i<n1;i++)
	{
	    x[i]=a[n1-i-1];
	}  
	for(int i=0;i<n2;i++)
	{
	    y[i]=b[n2-i-1];
	}//x并不是string形式了
	
	if(n1<n2)
    {
    	for(int i=n1;i<n2;i++)
		    x[i]='0'; 
	}
	else
	{
		for(int i=n2;i<n1;i++)
		    y[i]='0'; 
	}
	
	int n=max(n1,n2);
    int s[100];
    int f=0;
    for(int i=0;i<n;i++)
    {
    	int c=x[i]-48+y[i]-48+f;
    	if(c<10)
    	{
    		s[i]=c;
    		f=0;
		}
		else
		{
			s[i]=c-10;
			f=1;
		}	    
	}
	if(f==1)
	{
		s[n]=1;
	    n=n+1;
	}

	string r,l;
	for(int j=0;j<n;j++)
	{
	    r=s[n-1-j]+'0';
	    l=l+r;
    }
    cout<<l<<endl;<<l.length();
	return 0;		
}

可以看到最后l才化为string形式,才可以用l.length()函数。

注意string 的加减法,string只能和string形式的加,类似于python 中的append。

#include<iostream>
#include<string> 
#include<cmath>
#include<algorithm>
using namespace std;

int main()
{
	string a,b,s;
	while(cin>>a>>b)
    {
	while(a.length()<b.length())
	    a='0'+a;
	    s=b;
	while(a.length()>b.length())
	    b='0'+b;
	    s=a;
	int temp=0,n=0;
	for(int i=a.length()-1;i>=0;i--)
	{
		temp=a[i]-'0'+b[i]-'0'+n;//整数 
		if(temp<10)
		{
		    s[i]=temp+'0';
			n=0	;
		}
		else
		{
			s[i]=temp-10+'0';
			n=1;
		}
	}
	if(n==1)
	    s='1'+s;
	cout<<s<<endl;
    }
	return 0;		
}

加了循环输入之后,牛客可以通过。

五、

输入描述:

输入一个字符串。

输出描述:

输出字符串中最长的数字字符串和它的长度。如果有相同长度的串,则要一块儿输出,但是长度还是一串的长度

示例1

输入

abcd12345ed125ss123058789

输出

123058789,9

1、

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string a,temp={},s={};
	while(cin>>a)
	{
		int n=0;
		for(int i=0;i<a.length();i++)
		{
			if(a[i]>='0' && a[i]<='9')//开始标志 
			{
			   s+=a[i];
			}
			else
			{
				if(n<s.length())
				{
				   temp=s;
				   n=s.length();	
				}
				else if(n==s.length())
			    {
			    	temp+=s;
				}
				s={};
			}
		}
		if(n<s.length())
				{
				   temp=s;
				   n=s.length();	
				}
		else if(n==s.length())
			    {
			    	temp+=s;
				}
		s={};
		cout<<temp<<","<<n<<endl;
    }
	return 0;
}

一定要注意循环输入里对变量的初始化。

再有string 的初始化,a={}。

字符串当成整体的思想。

部分比较的思想。  

#include <iostream>
#include <string>
using namespace std;
int main()
{
	string str;
	while( cin>>str )
	{
		int i;
		int max = 0;
		string ss;
		string out;
		for(i = 0; i < str.size(); i++)
		{
			if(str[i] >= '0' &&str[i] <= '9')
			{
				ss += str[i];
				while(str[i+1] >= '0' &&str[i+1] <= '9')
				{
					i++;
					ss += str[i];
				}
				if(ss.size() > max)
				{
					max = ss.size();
					out = ss;
			        }
				else if(ss.size() == max)
				out += ss;
			}
			ss.clear();
		}
		cout<<out<<','<<max<<endl;
	}
	return 0;
}

ss.clear()的应用。

五、

功能: 求一个byte数字对应的二进制数字中1的最大连续数,例如3的二进制为00000011,最大连续2个1
    
输入: 一个byte型的数字
    
输出: 无
     
返回: 对应的二进制数字中1的最大连续数

输入描述:

输入一个byte数字

输出描述:

输出转成二进制之后连续1的个数

示例1

输入

3

输出

2

1、位运算

2、

#include<iostream>
#include<string>
#include<cmath>
using namespace std;

int main()
{
	int n;
	while(cin>>n)
	{
		int count=0,maxCount=0;
		while(n)
		{
			if(n&1)//表示有1存在,下一次循环如果还有1,也会继续。
			{
				++count;
				maxCount=max(count,maxCount);
			}
			else
				count=0;
			n=n>>1;
		}
		cout<<maxCount<<endl;
	}
	return 0;
}

利用了位运算

3、

#include <iostream>
#include <string>
using namespace std;
int main()
{
	int x;
	while(cin>>x)
	{
		int s[50]={0};
		int i=0;
		while(x>0)
		{
			s[i]=x%2;//逆序存放的二进制数 
			x=x/2;
			i++;
		}
		int m=0,n=0;
		for(int j=0;j<i;j++)
		    cout<<s[j]<<" ";
		cout<<endl; 
		for(int j=0;j<i;j++)
		{
		    if(s[j]==1)
			{
			    n++; 
				while(s[j+1]==1)
				{
				    j++;
				    n++;
				}	
			}
			else
			{
				n=0;
			}
			if(m<n)
			    m=n;	
		} 
		cout<<m<<endl;
	}
	return 0;
}

六、

题目描述

对字符串中的所有单词进行倒排。

说明:

1、每个单词是以26个大写或小写英文字母构成;

2、非构成单词的字符均视为单词间隔符;

3、要求倒排后的单词间隔符以一个空格表示;如果原字符串中相邻单词间有多个间隔符时,倒排转换后也只允许出现一个空格间隔符;

4、每个单词最长20个字母;

输入描述:

输入一行以空格来分隔的句子

输出描述:

输出句子的逆序

示例1

输入

I am a student

输出

student a am I

 1、字符串处理

插入

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string s1, s2, s3;
    s1 = s2 = "1234567890";
    s3 = "aaa";
    s1.insert(5, s3);
    cout << s1 << endl;
    s2.insert(5, "bbb");
    cout << s2 << endl;
}

删除

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string s1, s2, s3;
    s1 = s2 = s3 = "1234567890";
    s2.erase(5);
    s3.erase(5, 3);
    cout<< s1 <<endl;
    cout<< s2 <<endl;
    cout<< s3 <<endl;

}

提取字符串

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string s1 = "first second third";
    string s2;
    s2 = s1.substr(6, 6);
    cout << s1 << endl;
    cout << s2 << endl;

}

查找

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string s1 = "apple google apple iphone";
    //从0开始查找"google"的位置
    int idx = s1.find("google", 0);
    cout << idx << endl;

    //统计apple出现的次数
    int idx_app = s1.find("apple",0);//从0开始查找 
    //npos大于任何有效下标的值
    int num = 0;
    while (idx_app != string::npos)
    {
        num++;
        cout << "找到的索引:" << idx_app << endl;
        idx_app+=5;
        idx_app = s1.find("apple", idx_app);//从idx_app开始查找 
    }

    cout << num << endl;

}

2、

#include<iostream>
using namespace std;
int  main()
{
   string a;
   while(getline(cin,a))
   {
   	    cout<<a<<endl;
   	    int s,e;
   	    e=a.length();
	    for(int i=a.length()-1;i>=0;i--)
		{
			if(a[i]==' ')
			{
				s=i;
				for(int j=s+1;j<e;j++)
				{
				    cout<<a[j];	
				}
		        cout<<" ";
		        e=s;
			}	
		}
		for(int j=0;j<e;j++)
		    cout<<a[j];
		cout<<endl;
   }
   return 0;
}

3、

#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main()
{
	string str;
	while(getline(cin,str))
	{
		vector<string>svec;
		svec.clear();
		string temp="";
		for(int i=0;i<str.size();++i)
		{
			if(str[i]>='a' && str[i]<='z' || str[i]>='A' && str[i]<='Z')
			    temp+=str[i];//单个单词的读入
			else
			{
			    if(temp.size()>0)
			    {
			        svec.push_back(temp);//利用vector容器,挨个放入,最后逆序输出
			        temp="";
			    }
			}
		}
		if(temp.size()>0)
		    svec.push_back(temp);
		for(int i=svec.size()-1;i>0;--i)
		    cout<<svec[i]<<' ';
		cout<<svec[0]<<endl;
	}
	return 0;
}

该方法利用vector的特性,可以处理特殊字符。

4、  

#include<iostream>
using namespace std;
int  main()
{
   string b;
   while(getline(cin,b))
   { 
        string a;
        int n=0;
   	    for(int i=0;i<b.length();i++)
   	    {
   	        if(b[i]>='a'&&b[i]<='z'||b[i]>='A'&&b[i]<='Z')
			    a=a+b[i];
			else
			{
			    if(n<=a.length())//设置标志,加空格
				    a=a+' ';
					n=a.length()+1;   	
			}	
		}
		int l;//边界空格输出条件 
		if(a[a.length()-1]==' ')
		    l=a.length()-1;
	    else
	        l=a.length();
   	    int s,e;
   	    e=l;
	    for(int i=l-1;i>=0;i--)
		{
			if(a[i]==' ')
			{
				s=i;
				for(int j=s+1;j<e;j++)
				{
				    cout<<a[j];	
				}
		        cout<<" ";
		        e=s;
			}	
		}
		for(int j=0;j<e;j++)
		    cout<<a[j];
		cout<<endl;
   }
   return 0;
}

注意设置标志,加空格。  

七、

战争游戏的至关重要环节就要到来了,这次的结果将决定王国的生死存亡,小B负责首都的防卫工作。首都位于一个四面环山的盆地中,周围的n个小山构成一个环,作为预警措施,小B计划在每个小山上设置一个观察哨,日夜不停的瞭望周围发生的情况。 一旦发生外地入侵事件,山顶上的岗哨将点燃烽烟,若两个岗哨所在的山峰之间没有更高的山峰遮挡且两者之间有相连通路,则岗哨可以观察到另一个山峰上的烽烟是否点燃。由于小山处于环上,任意两个小山之间存在两个不同的连接通路。满足上述不遮挡的条件下,一座山峰上岗哨点燃的烽烟至少可以通过一条通路被另一端观察到。对于任意相邻的岗哨,一端的岗哨一定可以发现一端点燃的烽烟。 小B设计的这种保卫方案的一个重要特性是能够观测到对方烽烟的岗哨对的数量,她希望你能够帮她解决这个问题。 

输入描述:
输入中有多组测试数据,每一组测试数据的第一行为一个整数n(3<=n<=10^6),为首都周围的小山数量,第二行为n个整数,依次表示为小山的高度h(1<=h<=10^9).
输出描述:
对每组测试数据,在单独的一行中输出能相互观察到的岗哨的对数。
输入例子1:
5
1 2 4 5 3
输出例子1:
7
1、
#include<iostream>
#include<string>
using namespace std;
int main()
{
	while(1)
	{
		int n,m[100]={0};
		cin>>n;
		for(int i=0;i<n;i++)
		    cin>>m[i];
		    
		int num=0,h;
		for(int i=0;i<n-1;i++)
		{
			h=m[i+1];
			num++;
			for(int j=i+2;j<n;j++)
			{
				if(m[j]>h)
				{
					num++;
					h=m[j];
				}
			}
		}
		cout<<num<<endl;
    }
	return 0;
}

卡在了70%,对题目理解感觉很迷惑,环形的话,给的例子可不止有7条。上述程序瞎猫碰到死耗子了。真正的题意两山之间的山小于等于两山之间的高度才可以看的到

2、

#include<iostream>
#include<string>
using namespace std;
int main()
{
	int b[10]={};
	int a[]={1,2,3,4,5};
	for(int i=0;i<5;i++)
	{
		b[i]=a[(i+2)%5];
		cout<<b[i]<<" ";
	}
}

利用余数,循环输出。

#include<iostream>
#include<string>
using namespace std;
int main()
{
	int n; 
	while(cin>>n)
	{
		int m[100]={0},x[100]={0};
		for(int i=0;i<n;i++)
		    cin>>m[i];
		    
		int Max=0,index=0;
		for(int i=0;i<n;i++)
		{
			if(m[i]>Max)
			{
				Max=m[i];
				index=i;
			}
		}
		for(int i=0;i<n;i++)
		{
			x[i]=m[(i+index)%n];//将最大值移到前面 
	    }
		
		int num=0;
		for(int i=0;i<n-1;i++)
		{
			num++;
			int h=x[i+1];
			if(h<=x[i])
			{
				for(int j=i+2;j<n;j++)
				{	
					if(x[j]>=h&&x[j]<=x[i])
					{
						num++;
						h=x[j];
					}
					else if(x[j]>=h&&x[j]>x[i])
					{
						num++;
						break;
					}
					/*else if(x[j]<h)
					{
						break;
					}*/
				}
		    }
		    int flag=0;
		    for(int i=1;i<n-1;i++)
		    {
		    	if(x[i]>x[n-1])
		    	{
		    		flag=1;
		    		break;
				}
			}
			
			if(flag==1)
			    num++;
		} 
		cout<<num;
    }
	return 0;
}

还是70%的通过率。问题不知道出在哪。  

 

八、

小明同学学习了不同的进制之后,拿起了一些数字做起了游戏。小明同学知道,在日常生活中我们最常用的是十进制数,而在计算机中,二进制数也很常用。现在对于一个数字x,小明同学定义出了两个函数f(x)和g(x)。 f(x)表示把x这个数用十进制写出后各个数位上的数字之和。如f(123)=1+2+3=6。 g(x)表示把x这个数用二进制写出后各个数位上的数字之和。如123的二进制表示为1111011,那么,g(123)=1+1+1+1+0+1+1=6。 小明同学发现对于一些正整数x满足f(x)=g(x),他把这种数称为幸运数,现在他想知道,小于等于n的幸运数有多少个? 

输入描述:
每组数据输入一个数n(n<=100000)
输出描述:
每组数据输出一行,小于等于n的幸运数个数。
输入例子1:
21
输出例子1:
3
#include<iostream>
#include<string>
#include<cmath>
using namespace std;

int Ten(int x)
{
	int s=0;
	while(x>0)
	{
		s=s+x%10;
		x=x/10;
	}
	return s;
}
int Sec(int x)
{
	int s=0;
	while(x>0)
	{
		s=s+x%2;
		x=x/2;
	}
	return s;
}
int main()
{
    int n;
    while(cin>>n)
    {
    	int num=0;
    	for(int i=1;i<=n;i++)
    	{
    		if(Ten(i)==Sec(i))
    		{
    			num++;
			}
		}
		cout<<num<<endl;	
	} 
	return 0;
}

 九、 

 给你两个集合,要求{A} + {B}。 注:同一个集合中不会有两个相同的元素。 

输入描述:
每组输入数据分为三行,第一行有两个数字n,m(0 ≤ n,m ≤ 10000),分别表示集合A和集合B的元素个数。后两行分别表示集合A和集合B。每个元素为不超过int范围的整数,每个元素之间有个空格隔开。
输出描述:
针对每组数据输出一行数据,表示合并后的集合,要求从小到大输出,每个元素之间有一个空格隔开,行末无空格。
输入例子1:
3 3
1 3 5
2 4 6
输出例子1:
1 2 3 4 5 6
#include<iostream>
#include<string>
#include<cmath>
using namespace std;

int main()
{
	int n,m;
	while(cin>>n>>m)
	{
		int n1[10000]={0},m1[10000]={0},s[20000]={0};
		for(int i=0;i<n;i++)
		{
		    cin>>n1[i];
		    s[i]=n1[i];
		}
		for(int i=0;i<m;i++)
		{
		    cin>>m1[i];
		    s[i+n]=m1[i];
		}
		for(int i=0;i<n+m-1;i++)
		{
		    int Min=i;
			for(int j=i+1;j<n+m;j++)
			{
				if(s[Min]>s[j])
				{
					Min=j;
				}
			}
			int temp=0;
			temp=s[i];
			s[i]=s[Min];
			s[Min]=temp;
		}
		for(int i=0;i<n+m-1;i++)
		    cout<<s[i]<<" ";
		cout<<s[n+m-1]<<endl;	
	}
	return 0;
}

 

这样的话没有考虑去重。

2、

#include<iostream>
#include<iterator>
#include<set>
 
using namespace std;
int main()
{
    int n, m;
    while (cin >> n, cin >> m)
    {
        set<int> st;
        int num;
        for (int i = 0; i < n + m; ++i)
        {
            cin >> num;
            st.insert(num);//自动插入排序 
        }
        int size = st.size();
        set<int>::iterator it = st.begin();
        for (int i = 0; i < size - 1; ++i)
        {
            cout << *it << " ";
            ++it;
        }
        cout << *it << endl;
    }
    return 0;
}

利用set特性,去重.

3、set

#include<iostream>
#include<set>
 
using namespace std;
int main()
{
    int s[]={1,3,6,9,3,4,5};
    set<int> st;
    for(int i=0;i<7;i++)
    {
    	st.insert(s[i]);
	}
	int n;
	n=st.size();
	cout<<n<<endl;//排好后的个数
	set<int>::iterator it;
	for(it=st.begin();it!=st.end();it++)
	{
		cout<<*it<<" ";
	}
	cout<<endl;
	return 0;
}

#include<iostream>
#include<set>
 
using namespace std;
int main()
{
    int s[]={1,3,6,9,3,4,5};
    set<int> st;
    for(int i=0;i<7;i++)
    {
    	st.insert(s[i]);
	}
	int n;
	n=st.size();
	cout<<n<<endl;//排好后的个数
	set<int>::iterator it=st.begin();
	for(int i=0;i<n-1;i++)
	{
		cout<<*it<<" ";
		it++;
	}
	cout<<*it;
	cout<<endl;
	return 0;
}

十、

 
小B感兴趣的是,一个数A如果按2到A-1进制表达时,各个位数之和的均值是多少?她希望你能帮她解决这个问题? 所有的计算均基于十进制进行,结果也用十进制表示为不可约简的分数形式。

输入描述:
输入中有多组测试数据,每组测试数据为一个整数A(1 ≤ A ≤ 5000)
输出描述:
对每组测试数据,在单独的行中以X/Y的形式输出结果。
示例1

输入

5
3

输出

7/3
2/1
#include<iostream>
#include<set>
 
using namespace std;

int Sum(int n)//余数和 
{
	int s=0;
	for(int i=2;i<n;i++)
	{
		int y=n;
		while(y>0)
		{
			s=s+y%i;
			y=y/i;
		}
	}
	return s;
}

int Yue(int s,int n)
{
    for(int i=n;n>=1;i--)
	{
		if(s%i==0&&n%i==0)
		{
			cout<<s/i<<'/'<<n/i<<endl;
			break;
		}	
	}		
} 

int main()
{
    int n;
    while(cin>>n)
    {
        Yue(Sum(n),n-2);
	}
	return 0;
}

  余数求和与最大公约数的算法。

posted on 2018-04-08 09:26  箬笠蓑衣  阅读(6726)  评论(0编辑  收藏  举报