最近做的一些比较基础的笔试面试题目

最近也参加了一些笔试,也看了一些笔试的题目。感觉不管是一些普通的公司还是牛一些的,都会考一些基本的编程题和算法题。毕竟笔试的时间也就是那么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;
}

该题目即为微软100题的29题: http://blog.csdn.net/v_july_v/article/details/6870251


百度

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. 一个数字串Nf(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;
}

5.   腾讯笔试:把两个数和告诉 A ,积告诉 B ,求这两个数是什么

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





你可能感兴趣的:(最近做的一些比较基础的笔试面试题目)