(一)归并排序
(1)求数组中的最大值
#include<bits/stdc++.h>
using namespace std;
class GetMax
{
public:
static int GetArrMax(vector<int> arr, int L, int R)
{
if(L==R)
return arr[L];
int mid=(L+R)>>1;
int LeftMax= GetArrMax(arr,L,mid);
int RightMax=GetArrMax(arr,mid+1,R);
return max(LeftMax,RightMax);
}
};
int main()
{
vector<int> a{3,6,1,8,4,7,90,2,8,03,6,9};
GetMax m;
cout << m.GetArrMax(a,0,a.size()-1) << endl;
}
(2)归并排序
#include<bits/stdc++.h>
using namespace std;
class Max
{
public:
void merge(vector<int> &arr, int L, int mid, int R)
{
vector<int> tmp(R-L+1);
int i = L;
int j = mid + 1;
int k=0;
while (i <= mid && j <= R)
tmp[k++]=arr[i]<=arr[j]? arr[i++] : arr[j++];
while (i <= mid)
tmp[k++]=arr[i++];
while (j <= R)
tmp[k++]=arr[j++];
// 将已排序的数据赋值给原数组
for(auto i: tmp)
arr[L++]=i;
}
void mergeSort(vector<int> &arr, int L, int R)
{
if(L==R)
return;
int mid=(L+R) >>1;
mergeSort(arr, L, mid);
mergeSort(arr, mid + 1, R);
// 归并
merge(arr, L, mid, R);
}
};
int main()
{
vector<int> v={3,6,1,5,8,4,9};
Max k;
k.mergeSort(v, 0, v.size() - 1);
for (int i = 0; i < v.size(); ++i)
cout << v[i] << " ";
cout << endl;
}
归并排序总结:
(1)实质就是简单递归,左排序右排序使得整体有序
(2)借用外排序的方法
(3)利用master公式求解时间复杂度 O(nlogn) 额外空间复杂度O(n)
(3)master公式
T [n] = aT[n/b] + f (n)(直接记为T [n] = aT[n/b] + O (N^d))
①当d<logb a时,时间复杂度为O(n^(logb a))
②当d=logb a时,时间复杂度为O((n^d)*logn)
③当d>logb a时,时间复杂度为O(n^d)
(4)归并排序的拓展
小和问题:
在一个数组中,每一个数左边比目前数要小的数累加起来,叫这个数组的小和
#include<bits/stdc++.h>
using namespace std;
class Max
{
public:
//求小和问题
int merge(vector<int> &arr, int L, int mid, int R)
{
vector<int> tmp(R-L+1);
int i = L;
int j = mid + 1;
int k=0;
int sum=0;
while (i <= mid && j <= R)
{
if(arr[i]<=arr[j])
sum+=(R-j+1)*arr[i];
tmp[k++]=arr[i]<=arr[j]? arr[i++] : arr[j++];
}
while (i <= mid)
tmp[k++]=arr[i++];
while (j <= R)
tmp[k++]=arr[j++];
// 将已排序的数据赋值给原数组
for(auto i: tmp)
arr[L++]=i;
return sum;
}
int mergeSort(vector<int> &arr, int L, int R)
{
if(L==R)
return 0;
int mid=(L+R) >>1;
return mergeSort(arr, L, mid)+ mergeSort(arr, mid + 1, R)+merge(arr, L, mid, R);
}
};
int main()
{
vector<int> v={1,4,2,3,7};
Max k;
cout << k.mergeSort(v, 0, v.size() - 1) << endl;
}
求逆序对问题:
与求小和问题类似
#include<bits/stdc++.h>
using namespace std;
class Max
{
public:
//求小和问题
int merge(vector<int> &arr, int L, int mid, int R)
{
vector<int> tmp(R-L+1);
int i = L;
int j = mid + 1;
int k=0;
int sum=0;
while (i <= mid && j <= R)
{
//求逆序对
if(arr[i]>arr[j])
sum+=(mid-i+1);
tmp[k++]=arr[i]<=arr[j]? arr[i++] : arr[j++];
}
while (i <= mid)
tmp[k++]=arr[i++];
while (j <= R)
tmp[k++]=arr[j++];
// 将已排序的数据赋值给原数组
for(auto i: tmp)
arr[L++]=i;
return sum;
}
int mergeSort(vector<int> &arr, int L, int R)
{
if(L==R)
return 0;
int mid=(L+R) >>1;
return mergeSort(arr, L, mid)+ mergeSort(arr, mid + 1, R)+merge(arr, L, mid, R);
}
};
int main()
{
vector<int> v={1,4,2,3,7};
Max k;
cout << k.mergeSort(v, 0, v.size() - 1) << endl;
}
荷兰国旗问题(一)
给定一个数组nums和一个数target,把小于等于num的放左边,大于num的放右边,要求额外空间复杂度为O(1),时间复杂度为O(N)
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<int> nums{3,6,1,5,8,3,6,2,7,3,9,4,6};
int target=4;
int place=-1;
for(int i=0;i<nums.size();i++)
{
if(nums[i]<=target)
{
swap(nums[++place],nums[i]);
}
}
for(auto i: nums)
cout << i << endl;
}
荷兰国旗问题(二)
给定一个数组nums和一个数target,把小于target的放左边,大于target的放右边,等于target的放中间,要求额外空间复杂度为O(1),时间复杂度为O(N)
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<int> nums{3,6,4,7,4,8,2,4,3,5,8,3,4,4};
int target=4;
int place1=-1;
int place2=nums.size();
for(int i=0;i<nums.size();)
{
if(i==place2)
break;
if(nums[i]<target)
{
swap(nums[++place1],nums[i++]);
}else if(nums[i]>target)
{
swap(nums[--place2],nums[i]);
}else i++;
}
for(auto i: nums)
cout << i << endl;
}
(5)快速排序的三种方法
(一)选定每次选用最后一个数作为划分
#include<bits/stdc++.h>
using namespace std;
class Quick
{
public:
void QuickSort(vector<int> &arr,int L, int R)
{
if(L<R) //判断是否满足排序条件,递归的终止条件
{
int i = L, j = R;
int x = arr[R];
while(i<j)
{
while(i<j && arr[i] <= x)
i++;
if(i<j)
arr[j--] = arr[i];
while(i<j && arr[j] >= x)
j--;
if(i<j)
arr[i++] = arr[j];
}
arr[i] = x;
QuickSort(arr, L ,i-1);
QuickSort(arr, i+1 ,R);
}
}
};
int main()
{
vector<int> nums{3,6,4,7,4,8,2,4,3,5,8,3,4,4};
//快速排序
int L=0,R=nums.size()-1;
Quick m;
m.QuickSort(nums,L,R);
for(auto i: nums)
cout << i <<" ,";
cout <<endl;
}
(二)选用随机数做哨兵
(三)选用类似荷兰国旗的方法