最近也参加了一些笔试,也看了一些笔试的题目。感觉不管是一些普通的公司还是牛一些的,都会考一些基本的编程题和算法题。毕竟笔试的时间也就是那么1,2个小时。而其实这些基础的编程和算法题是需要考察一个人的基础扎实度的,这些题目的特点是,如果基础不扎实,思路没想到,这些题目也会话费很长时间而不得解,如果找到正确的方法,这些题目都会迎刃而解。所以说,这些题目看似简单,但是实则也是很有区分度的,也应该认真对待。
Amazon
1. 先给出一个原始的整数序列A,判断另外一个序列B是否可以通过A在栈的push和pop操作得到。例如:1,2,3,4,,然后再给出一个3,2,4,1。则B可以通过A push1 push2 push3 pop3 pop2 push4 pop4 pop1得到。使用程序输出push和pop操作顺序。
思路:关键在于比对序列A和序列B的对应关系,如果A中的数和B的不对应,则应该是push操作,使用一个临时堆栈s,保存push到s中的数,如果发现s的栈顶的数与B序列相等,则说明是pop出来的,则将s同样pop。然后继续循环操作比较B的下一个数。完整代码如下:
#include <iostream> #include <stack> //#define N 5 using namespace std; /* * 将a[N]的序列按照b[N]的序列输出的push、pop操作序列 */ void Fun(int *a, int *b, int len){ stack<int> s; int i=0,j=0; while(j<len){ //比对临时堆栈堆顶与b[N]关系,如果为空或不等,需要将a[N]内容压入,是一个push操作,否则弹出临时堆栈,是一个pop操作。 if(s.empty() || s.top() != b[j]){ s.push(a[i]); cout << "push "<<a[i]<<"| "; ++i; }else{ s.pop(); cout << "pop "<<b[j]<<"| "; ++j; } } cout <<endl; //如果为空,则说明b[N]可以由堆栈a[N]根据push、pop序列得到 if(s.empty()) cout<<"正确的序列"<<endl; else cout<<"错误的序列"<<endl; } int main(){ int i,N; //序列的数量 cin >> N; while(N!=0){ int *a = new int[N]; int *b = new int[N]; cout << "输入初始序列:"; for(i=0;i<N;i++){ cin >> a[i]; } cout << "输入变化后序列:"; for(i=0;i<N;i++){ cin >> b[i]; } Fun(a,b,N); cin >> N; } //system("pause"); return 0; }
百度
2. 求一个字符串S的全排列结果:
思路:可以想到,使用递归可以实现全排列,例如对于123,可以输出1(23)的排列,2(13)的排列,3(12),即对一个序列,从start位置,一直遍历到end位置,每次遍历递归调用,直到start=end时,递归结束,输出该序列。
#include <stdlib.h> #include <stdio.h> #define N 4 void Swap(char *a, char *b){ char temp; temp=*a; *a=*b; *b=temp; } void Arrange(char a[], int start, int end){ int i; char temp; if(start == end){ for(i = 0; i <= end; i++) printf(" %c ",a[i]); printf("\n"); }else{ for(i = start; i <= end; i++){ Swap(a+start,a+i); Arrange(a, start+1, end); Swap(a+start,a+i); } } } int main(){ printf("输入%d个字符:",N); char *a=(char *)malloc(sizeof(char)*N); for(int i=0;i<N;i++){ scanf("%c",a+i); } Arrange(a,0,N-1); printf("\n"); system("pause"); return 0; }这篇博客给了很多种该问题的不同变种: http://blog.csdn.net/zz198808/article/details/7657168
百度-面试题
3. 怎么手工计算从1到1亿的出现的所有数的和。
做这道题,我受了编程之美里面有一道找1的数量拿到题目的影响,上来就找数字出现的规律,虽然也找到了一些规律,但是计算还是很麻烦。事实上,我们想一下,我们计算一个顺序出现的数从1到N怎么算,使用高斯定理(1+N)*N/2,而高斯定理的思想就是顺序数列1+N=2+(N-1)=3+(N-2)=...即前后两两配对的。所以同样可以采用这种策略计算出现的数字的和。
可以这样分组:(0,99999999),(1,99999998),(2,99999997)(3,99999996)……(49999999,50000000),共50000000组,还剩下数字100000000。
这样每一组的数字之和都是:9*8=72
总和为:72*50000000+1=3600000001(36亿零1)
或者使用加法的竖列来观察。
从
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
……………………
到
9 9 9 9 9 9 9 9
得到一个8列、1亿行的数组
看其中任何一列:0-9都出现1千万次
解法如下:(0+1+2+3+4+5+6+7+8+9)*1千万*8列+1(1亿的)=45*8*1千万+1=36亿零1
参考的博客为:http://alchimie.iteye.com/blog/1423817
百度-笔试
4. 一个数字串N,f(N)是位数和N一样,各位总和也和N一样,但是数值上大于N的最小数
例如N = 020,那么f(N) = 101,如果不存在f(N),则f(N) = -1
思想是:
先计算数字串N的总和sum,然后需要判断数字串中第一个非0数字的位置pos和第一个非0数字a[pos]与总和sum的关系,分以下几种情况:
1) 如果N=1,则返回-1,不能找到该数
2) 当数串为全0时,返回-1
3) 当第一个非0数与sum相等时,如果pos=0,则返回-1,因为如果在第一位比a[pos]大,则总和超出sum了。否则,a[pos-1]=1
4) 当第一个非0数与sum不相等时,则第一个数为a[pos]+1.
将第一位确定之后,剩下的差值放在最后。
#include <stdlib.h> #include <stdio.h> #define N 5 //将剩余的几个数放在数组b中的最末尾 void AddLeft(int b[], int num, int len){ for(int i = len-1; num!=0 ; num/=10,--i){ b[i]=num%10; } } int Fun(int a[], int b[], int len){ int flag=0; int maxpos=-1; //第一个非0数的位置 int sum=0; //数串总和 if(len == 1) return -1; //只有一位,则不可能找到 for(int i=0;i<N;i++){ if(a[i] != 0 && flag==0){ maxpos=i; flag=1; } sum+=a[i]; } if(maxpos == -1) return -1; //为全0,则不可能找到 if(sum == a[maxpos]){ if(maxpos == 0) return -1; //如果非0为第一位,则不能得到 else{ b[maxpos-1]=1; //否则可以在大一位上设置为1 AddLeft(b, sum-1,N); return 1; } }else{ //当总和比第一个非0数要大时,可以在非0数的数位加1 b[maxpos]=a[maxpos]+1; AddLeft(b, sum-b[maxpos],N); return 1; } } int main(){ int a[N],b[N]={0}; printf("输入%d个数:",N); for(int i=0;i<N;i++){ scanf("%d",a+i); } if(Fun(a,b,N)!=-1){ printf("可以转化为:"); for(int i=0;i<N;i++){ printf("%d ",b[i]); } }else{ printf("不能转化!"); } printf("\n"); system("pause"); return 0; }
1-20的两个数把和告诉A,积告诉B,
A说不知道是多少,
B也说不知道,
这时A说我知道了,
B接着说我也知道了,
问这两个数是多少?
挺有意思的一道题:看似无从下手,其实主要解决点在这里:B说不知道之后,A即知道。则说明A中和的几种情况中,应该仅有一种导致乘积不能确定两个数是多少。应该从乘积最小的开始算起来。
如果两个数可以重复:
B=4时,可能是1*4或2*2,A=4,4=1+3,4=2+2。1,3两个数B可以确定为3,所以一定为2,2。
B=6时,可能是1*6或2*3。那么当A=5时,5=1+4,5=2+3,如果5=1+4,则B不能确定,只剩下2,3这种情况,所以两个数可以为2,3。
如果两个数不能重复,
A=5=2+3=1+4,如果是1,4,B=4=1*4,应该说知道,所以不是1,4,只能是2,3。这时B=6,6=1*6=2*3,A说知道了,如果是1,6的话,A=7=1+6=2+5=3+4,不满足。所以只能是2,3情况,A=5=1+4=2+3。A不能是1,4。所以最后确定两个数是2,3.
A=6=2+4=1+5,如果是1,5,B=5=1*5,应该说知道,所以不是1,5,只能是2,4。这时B=8,8=1*8=2*4,只能是2,4满足。
所以不论是可重复还是不能重复,一定有2,3,这种情况
百度-笔试
6. 编写函数,统计在某段英文文本中完整句子的数目,文本中只包括大小写字母,空格,点好(.),逗号(,)。
完整的句子必须包含至少一个字母并以点号,结束。
要求:完整的代码,达到目标;高效;简洁;
#include <stdio.h> #include <stdlib.h> int main(){ FILE *fp; char ch; char *dir="data.txt"; if((fp=fopen(dir,"rt"))==NULL){ printf("Cannot open file strike any key exit!"); return -1; } int num=0; //句子数量 int charNum=0; while((ch=getc(fp))!=EOF){ printf("%c",ch); if(ch!='.'){ if( (ch >='a'&& ch <='z') || (ch >='A'&& ch <='Z') ) charNum++; else charNum=0; }else if(charNum != 0){ num++; charNum=0; } } printf("\n句子数量是:%d\n",num); fclose(fp); system("pause"); return 0; }