算法复习——分治算法
侧重于分解:快速排序、次序选择
侧重于合并:归并排序、逆序计数、最大子数组
最大子数组问题
GetAcross(A, left, mid, right)
{
// mid左边
s_left = -INF, sum = 0;
for(i=mid to left) {
sum += A[i];
if (sum > s_left) {
s_left = sum;
}
}
// mid右边
s_right = -INF, sum =0;
for (i=mid+1 to right) {
sum += A[i];
if (sum > s_right) {
s_right = sum;
}
}
return (s_left + s_right);
}
MNC(A, left, right)
{
if (left >= right) return A[left];
else {
mid = (left + right)/2;
s1 = MNC(A, left, mid);
s2 = MNC(A, mid+1, right);
s3 = GetAcross(A, left, mid, right);
return max(s1, s2, s3);
}
}
归并排序问题
Merge(A, left, mid, right)
{
B[left..right] = A[left..right];
k = 0;
i = left, j = mid+1;
while(i<=mid and j<=right) {
if(B[i] <= B[j]) {
A[k] = B[i];
k++, i++;
}
else {
A[k] = B[j];
k++, j++;
}
}
while (i <= mid) {
A[k..right] = B[i..mid];
}
while (j <= right) {
A[k..right] = B[j..right];
}
return A[left..right];
}
MergeSort(A, left, right)
{
if(left >= right) return A[left]
else {
mid = (left + right)/2;
MergeSort(A, left, mid); // T(n/2)
MergeSort(A, mid+1, right); // T(n/2)
Merge(A, left, mid, right); // O(n)
return A[left..right];
}
}
逆序计数问题
Merge(A, left, mid, right)
{
B[left..right] = A[left..right];
k = 0;
i = left, j = mid+1;
s3 = 0;
while(i<=mid and j<=right) {
if(B[i] <= B[j]) {
A[k] = B[i];
k++, i++;
}
else {
A[k] = B[j];
k++, j++;
s3 += mid-i+1; // 如果B[i] > B[j], 那么B[i..mid] > B[j]
}
}
while (i <= mid) {
A[k..right] = B[i..mid];
}
while (j <= right) {
A[k..right] = B[j..right];
}
return A[left..right];
}
MergeCount(A, left, right)
{
if(left >= right) return 0,A[left]
else {
mid = (left + right)/2;
s1 = MergeCount(A, left, mid); // T(n/2)
s2 = MergeCount(A, mid+1, right); // T(n/2)
s3 = Merge(A, left, mid, right); // O(n)
return (s1+s2+s3), A[left..right];
}
}
快速排序算法
Partation(A, p, r)
{
x = A[r]; // 选取固定主元
i = p - 1;
for (j=p to r-1) {
if (A[j] <= x) {
exchange(A[i+1], A[j]);
i = i+1;
}
}
exchange(A[r], A[i+1]); // 把主元放到中间
return i+1;
}
QuickSort(A, p, r)
{
if (p < r) {
q = Partation(A, p, r);
QuickSort(A, p, q);
QuickSort(A, q+1, r);
}
}
时间复杂度为
随机化选取主元
Randomized-Partation(A, p, r)
{
k = random(p,r)
x = A[k];
exchange(A[k], A[r]);
//
i = p - 1;
for (j=p to r-1) {
if (A[j] <= x) {
exchange(A[i+1], A[j]);
i = i+1;
}
}
exchange(A[r], A[i+1]); // 把主元放到中间
return i+1;
}
Randomized-QuickSort(A, p, r) {
if (p < r) {
q = Randomized-Partation(A, p, r);
Randomized-QuickSort(A, p, q);
Randomized-QuickSort(A, q+1, r);
}
}
时间复杂度为
次序选择
找一个数组中第k小的元素
思路一:将整个数组排序(), 然后直接选取下标为left+k-1的元素即可
思路二:根据快速排序数组划分的思想,每次选取一个主元,然后把数组划分成左右两边,判断k 和 q-p+1的大小关系
SelectionProblem(A, left, right)
{
q = Randomized-Partation(A, left, right); //主要是使用了随机化快速排序,降低了时间复杂度
if (k == q-p+1){
return A[q];
}
else if (k < q-p+1) {
return SelectionProblem(A, left, q-1);
}
else {
return SelectionProblem(A, q+1, right);
}
}
时间复杂度是
基于比较的排序算法时间复杂度的下限是
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】