1、有序数组查找
假设一个数组,事先在你未知的情况下,以某一点分段有序排列。比如:(0,0,0,1,2,2,3 变成 0,0,1,2,2,3,0,定需要查找的数,在当前数组中查找,存在,返回ture,不存在,返回false。注意,这次数组中有重复的数字哦~
格式:
第一行输入数字n,接下来一行输入数组A[n],数组A[n]满足题目描述的条件,即分段有序。如:(2, 2, 0, 0, 1, 1);第三行输入要查找的target值。接下来一行输出true或者false。
样例输入
7 1 2 2 2 0 1 1 0
样例输出
true
#include<iostream> #include<algorithm> using namespace std; int main() { int n; cin>>n; int a[n]; for(int i=0;i<n;i++) cin>>a[i]; int target,mid; cin>>target; sort(a,a+n);//对输入的数组排序 int l=0, r=n-1;//二分查找 while(r>=l){ mid=(l+r)/2; /*if(target==a[mid]){ cout<<"true"<<endl; return 0; }*/ if(target>a[mid]) l=mid+1; else if(target<a[mid]) r=mid-1; else { cout<<"true"<<endl; return 0; } } cout<<"false"<<endl; return 0; }
2、特殊质数
7331是一个特殊的质数,因为我们去掉个位得到的733是一个质数;再次去掉个位得到的73又是一个质数;再去掉个位后得到的7依然是一个质数。对于形似这种的质数,我们称呼它为特殊质数。
写一个程序对给定的待求特殊质数的位数 N (1≤N≤8)求出所有对应位数的特殊质数(注意:数字1不被看作一个质数)。
输入包括一个整数,为待求特殊质数的位数 N。
输出长度为N的特殊质数列表,每行一个。
#include<iostream> using namespace std; int n; bool IsPrime(int a){ for(int i=2;i*i<a;i++){ if(a%i==0) return false; } return true; } void dfs(int sum,int cur){ if(cur==n) cout<<sum<<endl; for(int i=1;i<=9;i++){ if(i%2==0) continue; int asum=sum*10+i; if(IsPrime(asum)){ dfs(asum,cur+1); } } } int main(){ while(cin>>n){ dfs(2,1); dfs(3,1); dfs(5,1); dfs(7,1); } return 0; }
3、颜色排序
给定由n个图案,图案是红色,白色或者蓝色其中的一种,开始的时候他们的顺序是混乱的。请你设计一种排序算法,使得相同颜色的图案紧挨着,并且顺序为红,白,蓝。 为了方便,这里我们用0, 1, 2分别代替红白蓝三种颜色,请将他们排序出来~ 看这个例子,如:2 2 1 0 1 2 0,排序后变成0 0 1 1 2 2 2 注意:你不能使用库函数里面的排序算法哦~ 要求:时间复杂度 O(n),空间复杂度 O(1)
格式: 第一行输入数字n,第二行输入A[n], 其中数组里面只包含0, 1, 2三个数。第三行输出排好序的A[n]
样例输入:
8 1 2 1 2 0 0 0 2
样例输出 :
0 0 0 1 1 2 2 2
void SortByN(int a[], int length) { if (a == NULL || length < 0) { return; } //重新申请一个数组 const int N =200; int b[N]; //把新申请的数组全部初始化为0 for (int i = 0; i < N; ++i) { b[i] = 0; } //遍历a数组 for (int i = 0; i < length; ++i) { //例如:a[0] = 10;那么b[key] = b[10] = 1;表示有一个10; a[4] = 10; //那么b[key] = b[10] = 1+1 = 2,表示此时有两个10; int key = a[i]; ++b[key]; //意思就是b数组里面存放的是a数组中某个元素的个数,b[10]表示在a数 //组当中10出现的次数,b[0]表示0在a数组当中出现的次数 } int index = 0; for (int i = 0; i < N; ++i) { //如果b[0] = 0;表示a数组当中没有0;那么不执行这个循环;例如这里a是一个年龄数组,假设最小的年龄是18 //那么b[0] -- b[17]都是等于0;那么第二个循环都不执行,第一个循环执行,i加到了18;b[18]=2; //那么a数组当中有两个18;而且这两个18就是最小的数字,那么a[0] = 18; a[1] = 18; for (int j = 0; j < b[i];++j) { a[index] = i; ++index; } } }
4、单独的数字
一个整型数组中有一个元素只出现一次,其它元素都出现两次。求出只出现一次的元素。
要求:
线性时间复杂度,不能使用额外空间。
聪明的你能搞定吗?
格式:
第一行输入数字n,代表有n个数,根据题意,很明显n是奇数,
第二行输入数组A[i], i从0~n-1.
最后输出单独的数字。
样例1
输入:
7
1 3 2 0 3 2 1
输出:
0
/*那么这个题的突破口在哪里呢?注意这个数组的特殊性:其它数字都出现了两次,只有一个数出现了一次。可以想到运用异或运算,任何一个数字异或它自己都等于0。 如果我们从头到尾依次异或数组中的每一个数,那么最终的结果就是那个只出现一次的数字,因为其他出现两次的数字全部在异或中被抵消为0了(异或运算遵循交换分配率)。 举个栗子:2 3 4 2 3 所有数字依次异或运算:2 xor 3 xor 4 xor 2 xor 3 = (2 xor 2) xor (3 xor 3) xor 4= 0 xor 0 xor 4 = 4 最终结果4就是我们要找的那个只出现一次的数字。*/ #include<iostream> using namespace std; int main(){ int num; int f(int a[],int n,int &num); int n; cin>>n; int a[n]; for(int i=0;i<n;i++){ cin>>a[i]; } cout<<f(a,n,num)<<endl; return 0; } int f(int a[],int n,int &num){ for(int i=0;i<n;i++) num^=a[i]; return num; }
5、第一个没有出现的正数
给定一个数组,从 11 到 nn,找出数组中第一个没出现的正数。
例如:
给定[1,2,0]
,则返回 33。
给定[3,4,-1,1]
,则返回 22。
注意:
算法需要 \mathcal{O}(n)O(n) 的时间复杂度以及线性的空间复杂度。
#include<iostream> using namespace std; int main() { int n; cin>>n; int a[1000001]={0}; int tmp; for(int i=0;i<n;i++){ cin>>tmp; if(tmp>0) a[tmp]++; } for(int i=1;i<=n;i++){ if(a[i]==0){ cout<<i; return 0; } } }