笔试编程总结

1.现在将,有颜色的球放在一条直线上,球的颜色只有红色,黑色,并且每种球都是无限多的。如过现在一行球共有n个,那么没有三种相同颜色球相连的共有多少种?

当前球数为n时。
An 前两种球颜色相同。

Bn 前两种球颜色不同。

我的思路:递推

A3 = B3 = 2;
An = B(n-1)(n>3);

Bn = A(n-1) + B(n-1);

#include <iostream>
using namespace std;
int main(){
	int an=2,bn=2;
	int i=2,n,tmp;
	for(cin>>n ; i<n ;i++){
		tmp = an;
		an  = bn;
		bn  = an + bn;
	}
	cout << an + bn << endl;
	return 0;
} 
2.有一个数组序列,共有n个数字,先给出一个sum,需要得到所有的数字序列中的两个数a,b,有a+b = sum。

我的思路:

1.枚举限界O(n2)[利用条件更好点]

2.现将原来数组进行排序,然后假设a<b则从前向后枚举a,从后向前枚举b。

每当a+b<sum则有两种可能将a增大(向后枚举),将b增大(向后枚举,排序后不用考虑应为已经判断过了)

每当a+b>sum则有两种可能将a减小(向前枚举,排序后不用考虑应为已经判断过了),将b减小(向前枚举)

因此问题就可以通过一次枚举解决,复杂度max(O(n),O(nlogn)=O(nlogn);

#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=1001;
int num[maxn];
int main(){
	int i,n,l,r,sum;
	cin >> sum;
	for(cin >> n , i=0; i<n;i++){
		cin >> num[i];
	}
	sort(num,num+n);
	l=0,r=n-1;
	while(l<r){
		if(num[l]+num[r]>sum){
			r--;
		}else if(num[l]+num[r]<sum){
			l++;
		}else{
			cout << num[l]<<" "<< num[r] <<endl;
			l++;
		}
	}
	return 0;
}
3.有n个小朋友来参加小明的生日聚会,每个小朋友都只期望能和自己认识的朋友坐在一起,或者和朋友的朋友坐在一起,每一组小朋友的关系有p,q表示,说明p,q是朋友。这样关系共有m个,那么需要最少安排多少个桌子来是的每个小朋友都能按照期望就坐。
思路:最简单的并查集应用(精妙的应用见 “食物链” 解法)

#include <iostream>
using namespace std;
const int maxn=1001;
int father[maxn];
void init_set(int n){
	int i;
	for(i=0;i<=n;i++){
		father[i]=i;
	}
}
int find_father(int i){
	return father[i]==i ? i : father[i]=find_father(father[i]);
}
void union_set(int a,int b){
	father[find_father(a)]=find_father(b);
}
int main(){
	int n,m,i,count=0;
	cin >> n;
	init_set(n);
	for(cin >> m , i=0;i<m;i++){
		int a,b;
		cin >> a >> b;
		union_set(a,b);
	}
	for(i=1;i<=n;i++){
		count += father[i]==i;
	}
	cout << count<<endl;
	return 0;
}
4..共有n瓶药水,其中有一瓶是毒药,每瓶要水都会在喝下的一小时后产生作用。那么要知道他瓶药水是毒药,至少需要多少只小白鼠,若果有两瓶毒药呢?
最少需要x=(log2n)向上取整。

2代表生死,n代表总的药瓶总数2^x,唯一确定每瓶要的情况。

5.取石子游戏,现有n个石子,有A,B两人轮流取走,每次能取1到3个,取完最后一个石子胜利,问有n个石子,作为先手A的胜败。

最基本的Nim博弈,当一个后续状态为必胜时,后继状态有必败,为必败是所有后继为必胜状态。

有1,2,3为必胜,则4必败,则5,6,7,必胜8必败3n+1必败否则必胜。

因此则为 !(n%3==1)。

6.现在你有一组数(你知道他们分别是多少),又在这组数里面添加了一个数字,现在问你添加的数字是多少?

求得sn1(增加数之前的数列和),sn2(增加数后的数列和)

结果为sn2-sn1.

7.二分查找(简单而是用的经典啊)

int mybinary_search(const int num[],int n,int x){
	int l=0,r=n,m;
	while(l<r){
		m=(r+l)/2;
		if(num[m]==x){
			return m;
		}else if(num[m]<x){
			l=m+1;
		}else{//左闭,右开的原因 
			r=m;
		}
	}
	return -1;
} 

8.实现循环队列

#include <iostream>
using namespace std;
template <typename T>
class xqueue{
	public:
	int maxsize;
	T data[5];
	int front,rear;
	xqueue<T>(){
		maxsize=5;
		front=rear=0;
	}
	bool push(T val){
		if(full()){
			return false;
		}else{
			data[rear]=val;
			rear=(rear+1)%maxsize;
			return true;
		}
	}
	T get_front(){
		if(rear==front){
			return NULL;
		}else{
			return data[front];
		}
	}
	bool empty(){
		return front==rear;
	}
	void pop(){
		if(!empty()){
			front=(front+1)%maxsize; 
		}
	}
	bool full(){
		return (rear+1)%maxsize == front;
	}
	int size(){
		return (maxsize+(rear-front))%maxsize; 
	}
};
int main(){
	xqueue<string> que=xqueue<string>();
	while(!que.empty()){
		cout << que.get_front()<<endl;
		que.pop();
	}
	return 0;
} 



 




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值