一、排序
①插入排序
#define maxn 10000
int A[maxn],n;
void insertSort()
{
for(int i=2;i<=n;i++)
{
int temp=A[i],j=i;
while(j>1&&temp<A[j-1])
{
A[j]=A[j-1];
j--;
}
A[j]=temp;
}
}
②利用sort排序,注意sort的重写的排序规则
头文件#include
sort(起始位置地址,结束位置地址,排序规则)
sort(a,a+8,complare);
strcmp(s1,s2);
如果返回值 < 0,则表示 s1 小于 s2。
如果返回值 > 0,则表示 s1 大于 s2。
如果返回值 = 0,则表示 s1 等于 s2。
二、散列hash
空间换时间
开辟一个数组来确定存储查找的次数等信息(对于数据还是有一定的限制,若数据过大,开辟空间过大则不适合使用这个方法,或者也可以设计散列函数)
输入时可以用 char *gets(char *str)
三、二分
①二分查找
//在严格递增的序列里查找元素x
int binarySearch(int A[],int left,int right,int x)
{
int mid;
while(left<=right)
{
mid=left+(right-left)/2;
if(A[mid]==x)
{
return mid;
}
else if(A[mid]>x)
//递增序列此处用>,递减序列此处用<
{
right=mid-1;
}
else
{
left=mid+1;
}
}
return -1;
}
//求序列中的第一个大于等于x的元素的位置 A为递增序列
int lower_bound(int A[],int left,int right,int x)
{
int mid;
while(left<right)//注意这里没有等号
{
mid=left+(right-left)/2;
if(A[mid]<=x)
// 此处>=求的是第一个大于等于x的元素的位置
//此处<=求的是第一个小于等于x的元素的位置
{
right=mid;
}
else
{
left=mid+1;
}
}
return left;
}
//求递增序列中第一个大于x的元素的位置
int upper_bound(int A[],int left,int right,int x)
{
int mid;
while(left<right)//注意这里没有等号
{
mid=left+(right-left)/2;
if(A[mid]>x)
// 此处>求的是第一个大于x的元素的位置
//此处<求的是第一个小于x的元素的位置
{
right=mid;
}
else
{
left=mid+1;
}
}
return left;
}
//解决“寻找有序序列第一个满足某条件的元素的位置”
int solve(int left,int right)
{
int mid;
while(left+1<right)
{
mid=left+(right-left)/2
if(/*条件成立*/)
{
right=mid;
}
else
{
left=mid;
}
}
return right;
}
②二分法拓展:求根号二的近似值、半圆储水装置装水问题、木棒切割问题
③快速幂:
//快速幂 a的b次方%m
typedef long long LL;
LL binaryPow(LL a,LL b,LL c)
{
if(b==0)
{
return 1;
}
if(b%2==1)
{
return a*binaryPow(a,b-1,m)%m;
}
else
{
LL mul = binaryPow(a,b/2,m);
return mul*mul%m;
}
}
四、two points
例1:给定一个递增的正整数序列和一个正整数M,求序列中的两个不同位置的数a和b,使得它们的和恰好为M
例二:序列合并问题
//序列合并问题 AB序列均为递增序列,将二者合并为一个递增序列C
int merge(int A[],int B[],int C[],int n,int m)
{
int i=0,j=0,index=0;
while(i<n&&j>m)
{
if(A[i]<=B[j])
{
C[index++]=A[i++];
}
else
{
C[index++]=B[j++];
}
}
while(i<n)
{
C[index++]=A[i++];
}
while(j<m)
{
C[index++]=B[j++];
}
return index;//返回合并后的总长度
}
总结题型:使用两个下标志i,j对序列分别进行扫描
利用了数列递增的性质降低了复杂度
快速排序:
//快速排序
int Partition(int A[],int left,int right)
{
int temp=A[left];
while(left<right)
{
while(left<right&&A[right]>temp)
{
right--;
}
A[left]=A[right];
while(left<right&&A[right]<=temp)
{
left++;
}
A[right]=A[left];
}
A[left]=temp;
return left;
}
void quickSort(int A[],int left,int right)
{
if(left<right)
{
int pos=Partition(A,left,right);
quickSort(A,left,pos-1);
quickSort(A,pos+1,right);
}
}
生成随机数
头文件:#include<stdlib.h>
#incluude<time.h>
main函数第一句写srand((unsigned)time(NULL));
要输出[a,b]: rand()%(b-a+1)+a
随机选择算法
//从一个无序的数组中求出第K小的数
#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <ctime>
#include <cmath>
using namespace std;
//选取随机主元,对区间[left,right]进行划分
int randPartition(int A[],int left,int right)
{
srand((unsigned)time(NULL));
int p=(round(1.0*rand()/RAND_MAX*(right-left)+left));
swap(A[p],A[left]);
int temp=A[left];
while(left<right)
{
while(left<right&&A[right]>temp)
{
right--;
}
A[left]=A[right];
while(left<right&&A[right]<=temp)
{
left++;
}
A[right]=A[left];
}
A[left]=temp;
return left;
}
//随机选择算法,从A[left,right]中返回第K小的数
int randSelect(int A[],int left,int right,int k)
{
if(left==right)
{
return A[left];
}
int p=randPartition(A,left,right);
int M=p-left+1;
if(k==M)
{
return A[p];
}
if(k<M)
{
return randSelect(A,left,p-1,k);
}
else
{
return randSelect(A,p+1,right,k-M);
}
}
int main()
{
int A[10]={5,86,35,1,56,2,4,8,64,95};
for(int i=1;i<=10;i++)
{
cout<<randSelect(A,0,9,i)<<endl;
}
return 0;
}