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