for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
{
if(a[i]+a[j]==m)
cout << a[i] << a[j] << endl;
}
此方法效率低下原因:
使用two pointers方法:
使用two pointers方法的时间复杂度分析:
使用two pointers序列合并问题:
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++];
if(A[i]>B[j])
C[index++]=B[j++];
}
while(i<n)
C[index++]=A[i++];
while(j<m)
C[index++]=B[j++];
return index;
}
two pointers的实质是设置两个下标i,j对序列进行扫描(可以同向,也可以反向),时间复杂度一般为O(n)
//将数组A[L1,R1]与[L2,R2]合并为一个有序区间
void merge(int A[], int L1, int R1, int L2, int R2)
{
int i=L1,j=L2; //i指向L1,j指向L2
int temp[maxn],index=0; //temp为临时数组,index为其下标
while(i<=R1 && j<=R2)
{
if(A[i]<=A[j]) //如果A[i]<=A[j]
temp[index++]=A[i++]; //将A[i]放入数组中
else
temp[index++]=A[j++]; //否则将A[j]放入数组中
}
while(i<=R1) //将[L1,R1]剩余的数字放入到数组中
temp[index++]=A[i++];
while(j<=R2) //将[L2,R2]剩余的数字放入数组中
temp[index]=A[j++];
for(int i=0; i<index; i++) //将合并后的临时序列放回序列A中
A[L1+i]=temp[i];
}
void mergeSort(int A[],int left, int right)
{
if(left<right) //只要left小于right
{
int mid=(left+right)/2; //mid为中间
mergeSort(A,left,mid); //将一个序列分开后的左字序列
mergeSort(A,mid+1,right); //将一个序列分开后的右字序列
merge(A,left,mid,mid+1,right); //将左右子序列整合
}
}
void merge(int A[])
{
//step为组内元素个数,step/2表示组内左字区间个数
for(int step=2; step/2<=n; step*=2)
{
for(int i=1; i<=n; i+=step) //找出个数为step的每组第一数字的下标
{
int mid=i+step/2-1; //mid设置为每组元素中的中间位置
if(mid+1<=n)
{
merge(A,i,mid,mid+1,min(i+step-1,n)); //将左右区间进行合并,注意最后的那个数的位置
}
}
}
}
void mergeSort(int A[])
{
for(int step=2; step/2<=n; step*=2)
{
for(int i=1; i<=n; i+=step)
{
sort(A+i,A+min(i+step,n+1)); //注意这里由于sort必须是在数组中要排序的数列最后后一位的下一位,所以相比于之前+1
}
}
}
1.快速排序的定义:
2.用two powinters的思想构建一个快速排序的例子:
int Partition(int A[],int left,int right)
{
int temp=A[left]; //将最左边的值设置为temp
while(left<right) //循环一直到left与right相遇
{
while(left < right && A[right]>temp) //A[right]的值比temp大则将right下标--,找到第一个比temp小的值,然后将值放到前面
{
right--;
}
A[left]=A[right];
while(left < right && A[left]>temp) //A[left]的值比temp小,则left++。找到第一个比temp值大的值然后把他放到后面
{
left++;
}
A[right]=A[left];
}
A[left]=temp; //将temp放到既定位置
return left;
}
void quickSort(int A[],int left,int right) //整个递归的思想是:对一组无序的数组,
//先以第一个数为列,然后把他放到左边的数都比他小,右边的数都比他大,返回其位置,然后进行同样的操作,分别对于左子区间和右子区间
{
if(left<right)
{
int pos=partition(A,left,right); //partition函数的作用是把要放的数字,左边都比他小,右边都比他大,然后返回他的位置
quickSort(A,left,pos-1);
quickSort(A,pos+1,right);
}
}
5.设置随机数
#include
#include
#include
#include
using namespace std;
int main()
{
srand((unsigned)time(NULL)); //设置随机数字时,不要忘记加随机中子
for(int i=0; i<10; i++)
cout << rand() << " ";
}
#include
#include
#include
#include
using namespace std;
int main()
{
srand((unsigned)time(NULL)); //必须设置随机数种子
for(int i=0; i<10; i++) //随机输出[0,1]的随机数
cout << rand()%(2) << " ";
cout << endl;
for(int i=0; i<10; i++) //随机输出[3,7]的随机数
cout << rand()%(5)+3 << " ";
}
#include
#include
#include
#include
using namespace std;
int main()
{
srand((unsigned)time(NULL));
for(int i=0; i<10; i++)
{
cout << (int)(1.0*rand()/RAND_MAX*50000+10000) << " "; //设置一个长度为[10000,50000]的随机数
}
return 0;
}
7.在A[left…right]的范围内设置一个随机数,将A[p]作为主元进行划分,随机选取一个主元进行划分
int randPartition(int A[],int left,int right)
{
int p=1.0*rand()/RAND_MAX*(right-left)+left; //在[left,right]的范围内设置一个随机数
swap(A[p],A[left]); //将设置随机的数字和A[left]交换
int temp=A[left]; //将A[left]设置为临时变量
while(left<right) //进行调整
{
while(left < right && A[right]>temp)
right--;
A[left]=A[right];
while(left < right && A[left]<temp)
left++;
A[right]=A[left];
}
A[left]=temp;
return left; //相遇时,返回下标
}