pat-复习10 11 平方映射 堆排序 归并排序 快速排序 直接插入排序的比较 二分查找

平方映射

//1078 平方探测 
#include<bits/stdc++.h>
using namespace std;
bool isprime(int n){
	if(n<=1) return false;
	for(int i=2;i<=sqrt(n*1.0);i++){//<= 4.5 4本来可以<就漏掉了 
		if(n%i==0) return false;
	}
	return true;
}
int main(){
	int ms,n,_1;
	scanf("%d%d",&ms,&n);
	while(!isprime(ms)) ms++;
	int book[ms],book1[ms];
	fill(book1,book1+ms,0);
	map<int,int> ans;
	for(int i=0;i<n;i++){
		scanf("%d",&_1);
		ans[_1]=-1;
		for(int j=0;j<ms;j++){
			if(book1[(_1+j*j)%ms]==0){
				book[(_1+j*j)%ms]=_1;
				ans[_1]=(_1+j*j)%ms;
				book1[(_1+j*j)%ms]=1;
				break;
			}
		}
		if(i!=0) printf(" ");
		if(ans[_1]>=0)
		printf("%d",ans[_1]);
		else printf("-");
	}
	return 0;
	
} 
//平方探测法
//1145 
#include<bits/stdc++.h>
using namespace std;
bool isprime(int x){
	if(x<=1) return false;
	
	for(int i=2;i<=sqrt(x*1.0);i++){
		if(x%i==0) return false;
	}
	return true;
}
int main(){
	int ms,n,m,_1;
	scanf("%d%d%d",&ms,&n,&m);
	//if(!isprime(ms)) ms++;//本来应该用while又用成了if while才能实现循环找值 昨天也是这么错的  把while 写成if  1 
	 while(!isprime(ms)) ms++;
   int book[ms] ,book1[ms] ;
    fill(book,book+ms,0);
	fill(book1,book1+ms,0);
	
	for(int i=0;i<n;i++){
		int flag=1;
		scanf("%d",&_1);
		int j;
		for( j=0;j<ms;j++){//忘记插入后直接break 
			int _4=(_1+j*j)%ms;
			if(book1[_4]==0){
				book[_4]=_1;
				book1[_4]=1;
				flag=0;
				break;
			}
		}
		if(flag==1) printf("%d cannot be inserted.\n",_1);
	}
	int sum=0,_2;
	for(int i=0;i<m;i++){
		scanf("%d",&_2);
		for(int j=0;j<=ms;j++){
			sum++;
			int _3=(_2+j*j)%ms;
			if(book1[ _3]==0||book[ _3]==_2) break;
		}
	}
	
	printf("%.1lf\n",sum*1.0/m);
	return 0; 	
} 

堆排序

//堆排序 
#include<bits/stdc++.h>
using namespace std;
//向下调整
int heap[100],n=10;
 void downadjust(int low,int high){
 	int i=low,j=2*i;
 	while(j<=high){
 		if(j+1<=high){
 			if(heap[j+1]>heap[j]){
 				j=j+1;
			 }//选左右结点中的最大值 
		 }
		 if(heap[i]<heap[j]){
		 	swap(heap[i],heap[j]);
		 	i=j;//始终令i为调整节点 
		 	j=2*i;//左节点 
		 }else{
		 	break;
		 }
	 }
 }
 void create(){
 	for(int i=n/2;i>=1;i--){ 
	 downadjust(i,n);
	 }     //n/2为树的最后一个非叶节点 
 }
 void deletetop(){//删除栈顶元素 
 	heap[1]=heap[n--];
 	downadjust(1,n);
 }
 //插入元素需要用到的向上调整
 void upadjust(int low,int high){
 	int i=high;
 	int j=i/2;//双亲 
 	while(j>=low){
 		if(heap[i]>heap[j]){
 			swap(heap[i],heap[j]);
 			i=j;
 			j=i/2;
		 }else{
		 	break;
		 }
	 }
 } 
 //插入元素 
 void insert(int x){
 	heap[++n]=x;
 	upadjust(1,n);
 }
 void heapsort(){
   create();//建堆
   for(int i=n;i>1;i--){
   	  swap(heap[1],heap[i]);
	   downadjust(1,i-1);//i-1
   } 
 }
 int main(){
 	int _1;
 	for(int i=1;i<=10;i++){
 		scanf("%d",&_1);
		 heap[i]=_1;
	 }
	 insert(101);//1 insert 无误向上调整无误 
	 heapsort();//2向下调整 3建堆无误 
	 for(int i=1;i<=n;i++){
	 	printf(" %d",heap[i]);
	 }
	 return 0;
 }
//堆排序复盘 
#include<bits/stdc++.h>
using namespace std;
int heap[100],n=10;
void downadjust(int low,int high){
	int i=low,j=2*i;
	while(j<=high){ 
		if(j+1<=high&&heap[j+1]>heap[j]){//3 j+1也要验证是否在范围内是否存在
			j=j+1;
		}
		if(heap[j]>heap[i]){
			swap(heap[j],heap[i]);
			i=j;
			j=2*i;
		}else{
			break;
		}
	}
}
void deletetop(){
	swap(heap[1],heap[n--]);
	downadjust(1,n);
} 
void create(){
	for(int i=n/2;i>=1;i--){
		downadjust(i,n);
	}
}
void upadjust(int low,int high){
	int i=high,j=i/2;
	while(j>=low){
		if(heap[i]>heap[j]){
			swap(heap[i],heap[j]);
			i=j;
			j=i/2;
		}else{
			break;
		}
	}
}
void insert(int x){
	heap[++n]=x;
	upadjust(1,n);
}
void heapsort(){
	create();
	for(int i=n;i>1;i--){
		swap(heap[i],heap[1]);
		downadjust(1,i-1);
	}
}
int main(){
	int _1;
	for(int i=1;i<=n;i++){
		scanf("%d",&_1);
		heap[i]=_1;
	}
	insert(101);
	deletetop();
	heapsort();
	for(int i=1;i<=n;i++){
		printf(" %d",heap[i]);
	}
	printf("\n");

	
	return 0;
}
/*  4 5 68 4 2 1 7 6 3 7
//直接插入排序不是最终位置 需要相对检查  堆排序是最终位置可以和直接最终位置比对
//1098 
#include<bits/stdc++.h>
using namespace std;
int heap[110],insert[110],n;
void downadjust(int low,int high){
	int i=low,j=2*i;
	while(j<=high){
		if(j+1<=high&&insert[j+1]>insert[j]){
			j=j+1;
		}
		if(insert[j]>insert[i]){
			swap(insert[j],insert[i]);
			i=j;
			j=2*i;
		}else {
		break; 
	}
} 
}
int main(){
	scanf("%d",&n);
	
	for(int i=1;i<=n;i++){
		scanf("%d",&heap[i]);
	}
	for(int i=1;i<=n;i++){
		scanf("%d",&insert[i]);
	}
	int pre= insert[1],nt;
	for(int i=2;i<=n;i++){
	    if(insert[i]>=pre){
		pre=insert[i];	
		}else{
			nt=i;
			break;
		}
	}
	int flag=1;
	for(int i=nt;i<=n;i++){
		if(heap[i]!=insert[i]){
			flag=0;
		}
	}
	if(flag==1){
		printf("Insertion Sort\n");
		sort(heap+1,heap+nt+1);
		for(int i=1;i<=n;i++){
			if(i!=1) printf(" ");
			printf("%d",heap[i]);
		}
	}else{
		printf("Heap Sort\n");
		sort(heap+1,heap+n+1);
		int cnt;
		for(int i=n;i>=1;i--){
			if(insert[i]!=heap[i]){
			    cnt=i;
				break;
			}
		}
		swap(insert[1],insert[cnt]);
		downadjust(1,cnt-1);
		for(int i=1;i<=n;i++){
			if(i!=1) printf(" ");
			printf("%d",insert[i]);
		}
	}
	return 0;
	
}

归并排序

//归并排序 
#include<bits/stdc++.h>
using namespace std;
const int maxn=100;
int n;
void merge(int a[],int l1,int r1,int l2 ,int r2){
	int i=l1,j=l2;
	int temp[maxn],index=0;
	while(i<=r1&&j<=r2){
		if(a[i]<=a[j]){
			temp[index++]=a[i];
			i++;
		}else{
			temp[index++]=a[j];
		    j++;
		}
	}
	while(i<=r1) temp[index++]=a[i++];
	while(j<=r2) temp[index++]=a[j++];
	for(int i=0;i<index;i++){
		a[l1+i]=temp[i];
	}
}
void mergesort(int a[]){
	for(int step=2;step/2<=n;step*=2){
	for(int i=1;i<=n;i+=step){
		int mid=i+step/2-1;//左半区间的最后一个 
		if(mid+1<=n)//有可能不存在右子区间 
		merge(a,i,mid,mid+1,min(i+step-1,n));
	}
    }
}
void mergesortfz(int a[]){
	for(int step=2;step/2<=n;step*=2){
		for(int i=1;i<=n;i+=step){
			sort(a+i,a+min(n+1,i+step));//sort,reverse左闭右开 
		}
	}
}
int main(){
	int a[maxn];n=10;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	mergesort(a);//使用merge 
	//mergesortfz(a);//sort模拟 
	for(int i=1;i<=n;i++){
		printf(" %d",a[i]);
	}
	printf("\n");
	
}
//1089  差点被这题坑死  测试点4 5有问题,把编译器从clang 编程g++ 就完美通过了 
#include<bits/stdc++.h>
using namespace std;
int init[100],then[100],n;
void mergesort(int a[]){
	for(int step=2;step/2<=n;step*=2){
	int flag=0;
	for(int i=1;i<=n;i++){
		if(then[i]!=a[i])//这里出现问题应该是过程中的a 而不是直接带入init 
		flag=1;
	}
	for(int i=1;i<=n;i+=step){
		sort(a+i,a+min(i+step,n+1));
	}
	if(flag==0){
		for(int i=1;i<=n;i++){
			if(i!=1) printf(" ");
			printf("%d",a[i]);
		}
		break;//忘记 
	}
    }
    	
	}


int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&init[i]);
	}
	for(int i=1;i<=n;i++){
		scanf("%d",&then[i]);
	}
	int pre=then[1],nt;
	for(int i=2;i<=n;i++){
		if(pre<=then[i]){
			pre=then[i];
		}else{
			nt=i;
			break;
		}
	}
	int flag=0;
	for(int i=nt;i<=n;i++){
		if(init[i]!=then[i]){
		//	break;//break跑到标志前出错 
			flag=1;
			break;
		}
	}
	
	if(flag==0){
		printf("Insertion Sort\n");
		sort(then+1,then+nt+1);
		for(int i=1;i<=n;i++){
			if(i!=1) printf(" ");
			printf("%d",then[i]);
		}
	}else{
		printf("Merge Sort\n");
		/*int step;
		int pre1=then[1];
		for(int i=2;i<=n;i++){
			if(pre1<=then[i]){
				pre1=then[i];
			}else{
				step=i-1;//各个组之间未必有这样的大小关系 
				break;
			}
		}
		mergesort(then,step);
		for(int i=1;i<=n;i++){
			if(i!=1) printf(" ");
			printf("%d",then[i]);
		}*/
		mergesort(init);
	}
	return 0;
} 

快速排序

//快速排序 
#include<bits/stdc++.h>
using namespace std;
int partition(int a[],int left,int right){
	int temp=a[left];
	while(left<right){
	while(left<right&&temp<a[right]) right--;//指针是不断移动的 
		a[left]=a[right];
	while(left<right&&temp>=a[left]) left++;
		a[right]=a[left];
	
    }
    a[left]=temp;
    return left;
} 
void kysu(int a[],int left,int right){
	if(left<right){
	int mid=partition(a,left,right);
	kysu(a,left,mid-1);
	kysu(a,mid+1,right);
    }
}
int main(){
	int a[10];
	for(int i=0;i<10;i++){
		scanf("%d",&a[i]);
	}
	kysu(a,0,9);
	for(int i=0;i<10;i++){
		printf(" %d",a[i]);
	}
	return 0;
}
//除了在最终位置上还有保证左小右大 
//1101
#include<bits/stdc++.h>
using namespace std;
vector<long long > init,ccopy;
set<long long> ans;
//const int inf=100000000;//10^9最大值少一个0都不行 
const int inf=1000000000;
int main(){
	int n;
	long long _1;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%lld",&_1);
		init.push_back(_1);
	}
	ccopy=init;
	int bookmin[n],bookmax[n],mx=0,mn=inf;
	fill(bookmin,bookmin+n,inf);
	//fill(bookmax,bookmax+n,0);
	for(int i=n-1;i>=0;i--){
		if(ccopy[i]<mn){
			mn=ccopy[i];
			bookmin[i]=mn;
		}
	}
	sort(init.begin(),init.end());
	for(int i=0;i<n;i++){
		if(ccopy[i]>mx) mx=ccopy[i];
		if(init[i]==ccopy[i]&&ccopy[i]>=mx&&ccopy[i]<=bookmin[i]){//不是init  init已经排过序了应该是原序列的情况 
			ans.insert(ccopy[i]);
		}
	}
	printf("%d\n",ans.size());
    for(auto it=ans.begin();it!=ans.end();it++){
    	 if(it!=ans.begin()) printf(" ");
    	 printf("%lld",*it);
	}
	printf("\n");
	return 0;
}

二分查找  while(low<high)时返回位置 while(low<=high) 返回存不存在信息

//1010  //用了long long 一些正确了 
#include<bits/stdc++.h>
using namespace std;
string n1,n2;
long long int swit(char a){
	if(isdigit(a)){
		return a-'0';
	}else{
		return a-'a'+10;
	}
}
long long int findmax(string b){
	long long int max=-1;
	for(int i=0;i<b.size();i++){
		long long int _2=swit(b[i]);
		if(_2>max){
			max=_2;
		}
	}
	return max;
}
long long int jvswit(string c,long long int radix){
	long long int sum=0,cnt=0;
	for(int i=c.size()-1;i>=0;i--){
		sum+=swit(c[i])*pow(radix,cnt);
		cnt++;
	}
	return sum;
}
long long int erff(string d,long long int low,long long int high,long long int aim){
	while(low<=high){
      long long  int mid=(low+high)/2;
      long long  int _6=jvswit(d,mid);
	   /* if(_6<aim){//溢出也可能小于如果放在上面会误判溢出点  ,if else 当不是相互独立又相互包含关系时,顺序也非常重要 
		low=mid+1;
     	}*/
		 if(_6>aim||_6<0){//位数太多可能溢出 
			high=mid-1;
		}else if(_6==aim){
			return mid;
		}else{
			low=mid+1;//将这里的判断条件顺序改了就过了 
		}
	}
	return -1;
}
int main(){
	long long int tag,radix,_1,_2,_3,_4;
	cin>>n1>>n2>>tag>>radix;
	if(tag==1){
	 _1=jvswit(n1,radix);
	 _2=findmax(n2);
	 _4=max(_2+1,_1);//测试点1考察high不一定比low大此时要特判 
	 _3=erff(n2,_2+1,_4,_1);
	 if(_3==-1){
	 	printf("Impossible");
	 	return 0;
	 }else{
	 	printf("%d",_3);
	 }
	}else{
		_1=jvswit(n2,radix);
	 _2=findmax(n1);
	  _4=max(_2+1,_1);
	 _3=erff(n1,_2+1,_4,_1);
	 if(_3==-1){
	 	printf("Impossible");
	 	return 0;
	 }else{
	 	printf("%d",_3);
	 }
	}
	return 0;
}

总结

有很多小细节 需要注意 二分查找里long long 溢出判断 if else 上下相互包含要注意顺序

归并排序 每一组之间未必有大小关系

堆排序 全局算法 向下调整

快速排序  除了位置要在最终位置上 还要满足左小右大

直接插入排序 不是全局性算法,注意他的验证方法

加油 棒棒da~

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值