算法设计与分析复习02:分而治之算法

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 算法设计与分析复习02:分而治之算法,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

作者:非妃是公主
专栏:《算法》
个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩

在这里插入图片描述

专栏系列文章

算法设计与分析复习01:主方法求递归算法时间复杂度

算法设计与分析复习02:分而治之算法

算法设计与分析复习03:动态规划算法
算法设计与分析复习04:贪心算法

算法设计与分析复习05:回溯及分支限界

算法设计与分析复习06:随机化算法

算法设计与分析复习07:样题

复习重点

在这里插入图片描述

分而治之算法

全排列递归算法

在这里插入图片描述在这里插入图片描述

#include<vector>
#include<iostream>
using namespace std;
class Solution {
    vector<int> vis;
    void backtrace(vector<vector<int>>&res,vector<int>&nums,int first,int len, vector<int>& perm) {
        if (first == len) {
            res.push_back(perm);
        }
        else {
            for (int i = 0; i < len; i++) {
                if (vis[i])continue;
                perm.emplace_back(nums[i]);
                vis[i] = 1;
                backtrace(res, nums, first + 1, len, perm);
                vis[i] = 0;
                perm.pop_back();
            }
        }
    }
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>>res;
        vector<int> perm;
        vis.resize(nums.size());
        backtrace(res, nums, 0, nums.size(), perm);
        return res;
    }
};
int main() {
    Solution solution;
    vector<int> v = { 1,2,3 };
    vector<vector<int>> res = solution.permute(v);
    for (auto it = res.begin(); it != res.end(); it++) {
        for (auto it1 = it->begin(); it1 != it->end(); it1++) {
            cout << *it1 << " ";
        }
        cout << endl;
    }
    return 0;
}

矩阵乘法的Strassen算法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
[Strassen算法步骤](详解矩阵乘法中的Strassen算法 – 知乎 (zhihu.com))

算法分析:

T

(

n

)

=

{

O

(

1

)

n=1

7

T

(

n

2

)

+

O

(

n

2

)

n>1

T(n)=\left\{ \begin{matrix} O(1)& \text{n=1} \\ 7T(\frac{n}{2})+O(n^2)& \text{n>1} \end{matrix} \right.

T(n)={O(1)7T(2n)+O(n2)n=1n>1
主方法求得算法复杂度为:

n

l

o

g

2

7

n^{log_{2}{7}}

nlog27

棋盘覆盖

棋盘覆盖问题看下面这张图,由于要求期盼规模为

2

k

×

2

k

2^k\times2^k

2k×2k
有一定的局限性,但是是理解递归与分治的好问题,只看下面这张图:
在这里插入图片描述
每一个块对称选择。

线性时间选择

主要思想:利用快排,进行部分排序,不断缩小范围。
核心代码:
在这里插入图片描述
全部代码:

#include<vector>
#include<iostream>
#include<algorithm>
#include<queue>

using namespace std;

class Solution {
    struct num_mid {
        int pos;
        int num;
        bool operator<(const num_mid nm) {
            return this->num < nm.num;
        }
        num_mid(int p, int n) :pos(p), num(n) {}
    };
    int Partition(vector<int>& Vector, const int low, const int high) {
        //数据表类的共有函数
        int pivotpos;
        int pivot; //基准元素
        if (high - low > 5) {
            vector<num_mid>tmp;
            for (int i = low; i <= high - 4; i += 5) {
                sort(Vector.begin() + i, Vector.begin() + i + 4);
                tmp.push_back(num_mid(i + 2, Vector[i + 2]));
            }
            sort(tmp.begin(), tmp.end());
            pivotpos = low;
            pivot = Vector[tmp[tmp.size() / 2].pos];
            swap(Vector[low], Vector[tmp[tmp.size() / 2].pos]);
        }
        else {
            sort(Vector.begin() + low, Vector.begin() + high);
            pivotpos = low;
            pivot = Vector[(low + high) / 2]; //基准元素
            swap(Vector[low], Vector[(low + high) / 2]);
        }
        for (int i = low + 1; i <= high; i++)
            //检测整个序列, 进行划分
            if (Vector[i] < pivot) {
                pivotpos++;
                if (pivotpos != i)
                    swap(Vector[pivotpos], Vector[i]);
            } //小于基准的交换到左侧去
        Vector[low] = Vector[pivotpos];
        Vector[pivotpos] = pivot;
        //将基准元素就位
        return pivotpos; //返回基准元素位置
    }

    int QuickSort(vector<int>& L,
        const int left, const int right, int k) {
        //对元素Vector[left], ..., Vector[right]进行排序, 
        //pivot=L.Vector[left]是基准元素, 排序结束后它的
        //位置在pivotPos, 把参加排序的序列分成两部分,
        //左边元素的排序码都小于或等于它, 右边都大于它
        if (left < right) { //元素序列长度大于1时
            int res;
            int pivotpos = Partition(L, left, right); //划分
            if (pivotpos > k)
                res = QuickSort(L, left, pivotpos - 1, k);
            else if (pivotpos < k)
                res = QuickSort(L, pivotpos + 1, right, k);
            else
                return L[pivotpos];
            return res;
        }
        else
            return L[left];
    }
public:
    int findKthLargest(vector<int>& nums, int k) {
        int res = QuickSort(nums, 0, nums.size() - 1, nums.size() - k);
        return res;
    }
};

int main() {
    vector<int> v = { 3,2,3,1,2,4,5,5,6 };
    int res = QuickSort(v, 0, v.size() - 1, v.size() - 4);
    cout << res;    
}

时间复杂度分析:假设,基本实现二分,线性选择支点的时间复杂度为

O

(

n

)

O(n)

O(n),递归的时间复杂度如下:

T

(

n

)

=

T

(

n

2

)

+

O

(

n

)

T(n)=T(\frac{n}{2})+O(n)

T(n)=T(2n)+O(n)
依据主定理,时间复杂度为

O

(

n

)

O(n)

O(n)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/130516.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!