只有疯狂到自以为可以改变世界的人,最后才真的改变了世界!|

xu~~~

园龄:3年3个月粉丝:0关注:0

算法第二章

第二章

1、主方法

主方法是一个算法复杂度分析的一个很好的方法,但是只能用于特定的递归上,适合的递归形式为:
$$
T(n)=aT(n / b)+f(n)
$$
判断$n^{log b (a)}$与$f(n)$的大小关系

(1) 如果$n^{log b (a)}=O(f(n))$,那么该方法的复杂度为$O(f(n)*n^{log b (a)})$其中k>=0

(2) 如果$n^{log b (a)}>O(f(n))$,那么该方法的复杂度为$O(n^{log b (a)})$

(3) 如果$n^{log b (a)}<O(f(n))$,那么该方法复杂度为 $O(f(n))$

2、二分搜索

概念

二分搜索法,它充分利用了元素间的次序关系,采用分治策略,可在最坏的情况下用$O(log n)$完成搜索搜索任务。它的基本思想是,将n个元素分成个数大致相同的两半,取$a[n/2]$与欲查找的x作比较,如果$x=a[n/2]$则找到x,算法运算终止。

在这里插入图片描述

代码

void binarySearch(vector<int> &array, int element)
{
    int begin = 0;//begin代表的是,查找数组中的第一个元素的索引,初始为0
    int end = array.size()-1;//end此时代表的是查找数组的最后一位元素索引
    while (begin <= end)//当begin与end错过时,查找数组中不再有任何元素,搜索结束
    {
        int middle = (begin + end) / 2;
        if (array[middle] == element)
        {
            cout << "Search Success Index = " << middle << endl;
            return;
        }
        else if (element < array[middle])
        {
            end = middle -1;//更新end指针,指向新的搜索数组的末尾元素(不包括middle,所以要-1)
        }
        else if (element > array[middle])
        {
            begin = middle + 1;//更新begin指针,指向新的搜索数组的首元素(不包括middle,所以要+1)
        } 
    }
    cout<<"Element Not Find"<<endl;
    return;
}

时间复杂度分析

⼆分搜索算法的时间复杂性满足:
$$
T(n)=\left{\begin{array}{cc}
1 & n=1 \
1+T\left(\frac{n}{2}\right) & n>1
\end{array}\right.
$$

$$
\begin{aligned}
&T(n)=T\left(\frac{n}{2}\right)+1=T\left(\frac{n}{2^2}\right)+1+1 \
&=T\left(\frac{n}{22}\right)+2=T\left(\frac{n}{23}\right)+1+2 \
&=T\left(\frac{n}{23}\right)+3=T\left(\frac{n}{2k}\right)+k\
&\text { 令 } n=2^k \text {; 则 } k=\log n \
&T\left(\frac{n}{2^k}\right)+k=T(1)+k=1+\log n
\end{aligned}
$$

⼆分搜索算法的时间复杂度为:$O(log(n))$

2-3 改写二分搜索算法

请改写二分搜索算法,使得当搜索元素x不在数组中时,返回小于x的最大元素位置i和大于x的最小元素位置j。设a[0:n-1]是已排好序的数组。当搜索元素在数组中时,i和j相同,均为x在数组中的位置。

template<class T>
int binarySearch(T a[],const T&x,int left,int right,int &i,int &j){
int middle;
while(1eft<=right){
	middle=(1eft +right)/2;
	if(x==a[middle]){
		i=j= middle;
		return i;
	}
	if (x> a[middle])
		left=middle+1;
	else
		right=middle-1;
}
i=right;
j=1eft;
return 0;
}

3、大整数的乘法

m*n位大数时间复杂度为$O(mn)$

将n位二进制整数x和y都分为两段,每段的长为$\frac{n}{2}$

image-20220905220853315
$$
\begin{aligned}
&X=A 2^{\frac{n}{2}}+B \
&Y=C 2^{\frac{n}{2}}+D
\end{aligned}
$$

$$
X Y=\left(A 2^{\frac{n}{2}}+B\right) \times\left(C 2^{\frac{n}{2}}+D\right)=A C 2^n+(A D+B C) 2^{\frac{n}{2}}+B D
$$

$$
\begin{aligned}
&T(n)=\left{\begin{array}{cc}
O(1) & n=1 \
4 T\left(\frac{n}{2}\right)+O(n) & n>1
\end{array}\right. \
&T(n)=O\left(n^2\right)
\end{aligned}
$$

时间复杂度没有下降

对$XY$乘积式进行修改
$$
X Y=A C 2^n+((A-B)(D-C)+A C+B D) 2^{\frac{n}{2}}+B D
$$
时间复杂度改变
$$
\begin{aligned}
&T(n)=\left{\begin{array}{cc}
O(1) & n=1 \
3 T\left(\frac{n}{2}\right)+O(n) & n>1
\end{array}\right. \
&T(n)=O\left(n^{\log _2 3}\right)=O\left(n^{1.59}\right)
\end{aligned}
$$

2-4 大整数乘法的 $O(nmlog(3/2))$算法

给定两个大整数u和v,它们分别有m和n位数字,且 m≤n用通常的乘法求uv的值需要$O(mn)$时间。可以将u和v均看作有n位数字的大整数,用本章介绍的分治法,在$ O(n^{log3})$时间内计算uv的值。当m比n小得多时,用这种方法就显得效率不够高。试设计一个算法,在上述情况下用 $O(nm^{log(3/2)})$时间求出uv的值。
当m比n小得多时,将v分成n/m段,每段m位。计算uv需要n 次m位乘法运算。每次m位乘法可以用主教材中的分治法计算,耗时 $O(mlog3)$。因此,算法所需的计算时间为

$$O((n/m)m{log3})=O(nm)$$

4、合并排序

合并排序,大致思想便是先将数组中的元素拆分成若干小部分,然后再将这些小部分按照顺序进行重新组合,从而实现排序。

描述

image-20220905225006729

image-20220905225026993

时间复杂度分析

$$
T(n)=\left{\begin{array}{cc}
O(1) & n=1 \
2 T\left(\frac{n}{2}\right)+O(n) & n>1
\end{array}\right.
$$

$$
T(n)=O(n \log n)【主定理、递归】
$$

$$
\begin{aligned}
T(n) &=2 T\left(\frac{n}{2}\right)+c n=2\left(2 T\left(\frac{n}{4}\right)+c \frac{n}{2}\right)+c n \
&=2^2 T\left(\frac{n}{2^2}\right)+2 c n \
&=\cdots \
&=2^k T\left(\frac{n}{2^k}\right)+k c n
\end{aligned}
$$

$$
\begin{aligned}
\text { 令 } n &=2^k, k=\log n \
T(n) &=2^k T(1)+c n \log n \
&=O(n \log n)
\end{aligned}
$$

5、快速排序

快速排序算法通过多次比较和交换来实现排序,其排序流程如下:

(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。

(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于或等于分界值。

(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。

(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。

时间复杂度

  • 最坏(正好按照正序或逆序)

$$
\begin{gathered}
T_{\max }(n)=\left{\begin{array}{cc}
O(1) & n=1 \
T(n-1)+O(n) & n>1
\end{array}\right. \
\longrightarrow T_{\max }(n)=O\left(n^2\right)
\end{gathered}
$$

  • 最好(每次划分后都产⽣⼤⼩为n/2的两个区域)

$$
\begin{gathered}
T_{\min }(n)=\left{\begin{array}{cc}
O(1) & n=1 \
2 T\left(\frac{n}{2}\right)+O(n) & n>1
\end{array}\right. \
\rightarrow T_{\min }(n)=O(n \log n)
\end{gathered}
$$

本文作者:Is_zx

本文链接:https://www.cnblogs.com/erxuerxu/p/16659975.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   xu~~~  阅读(38)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起