每日算法

2020-07-05

最多需要猜测的次数与列表长度相同,这被称为线性时间(linear time)

二分查找的运行时间为对数时间(或log时间)

大O表示法:指出了算法的速度有多快(最糟糕的情况);运算时间为O(n),并非以秒为单位的速度,只是能够比较操作数,指出了算法运行时间的增速。

例如:有10亿个元素时,二分查找需要大约30毫秒,二分为简单查找的15倍 ,所以 简单查找为100毫秒。

可实际上,简单查找需要10亿毫秒,相当于11天。因为二分查找 和 简单查找的运算时间增速不同

O(log n);对数时间  二分查找

O(n);     线性时间  简单查找

O(n * log n);    快速排序

O(n²);       选择排序

O(n! );  这个非常慢。。。n的阶乘 例如:要去5个城市,规划出最短路线。。。

算法的速度指的并非时间,而是操作数的增速!

 

二分查找:O(log n);对数时间

  log232  = 5;(log以2为低,32的对数);

  python:binary_search函数接受一个有序数组和一个元素。如果指定的元素包含在数组中,就返回其位置(下标index)

  

 2020-07-08 时间真是挤出来的(月亮不睡我不睡)

选择排序:

数据存储两种基本方式:数组和链表

 

 

一般选择混合排序:链表数组。。。

 

 

 

 

 

 

 选择排序需要的总时间为O(n x n),即O(n²)

?:每次检索不是会少1吗,应该是O(n x 1/2 x n)。

但大O表示法省略1/2这样的常数~

查找最小值:

 

 

 

 

 

 

递归:

效率不怎么滴,指示方便理解。盒子里找钥匙的伪代码:

 

每个递归函数都有两部分:

  基线条件(base case) 和 递归条件(recursive case)

  递归条件指的是函数调用自己,

而基线条件则指的是函数不再调用自己,从而避免形成无限循环

 

 

栈(call stack):

递归调用栈,所以 1.循环替换递归 2.使用尾递归

 

 

 

 

简单的理解:

 

将可能返回的结果作为下次递归的参数传入

 

 

 

 

 

快速排序:

 

 

 其运行时间为:O(n log n)

 

分而治之(divide and conquer , D&C):

D&C算法是递归的,主要2个步骤:

1.找出基线条件,这种条件必须尽可能简单

2.不断将问题分解(缩小规模),直到符合基线条件

 

将一块 矩形 土地分为 n块大小相同的正方形:

首先:欧几里得算法

gcd(a,b) = gcd(b,a mod b);(困了,先睡了)

 

2020-7-10:

论证欧几里得算法:

gcd(a,b)=gcd(b,a mod b)

假设 c=gcd(a,b)  //c为a,b的最大公约数

则存在 m,n 使 a=mc,b=nc

令 r = a mod b //r为 a,b的余数

即存在 k 使 r = a - kb = mc - knc =  (m  - kn)c

故 gcd(b,a  mod b) = gcd(b,r) = gcd(nc , (m - kn)c) = gcd(n , (m - kn))c //则 c 为 b , a除以b的余数  的最大公约数

//因 c 为 n,(m-kn)的公约数 ; c 为(m-kn)的最大公约数

假设 d=gcd(n,m-kn) ,则存在x,y,使 n=xd, m-kn=yd

m-kn=yd 故 m=yd+kn ; 因 n=xd 故 m=yd+kxd=(y+kx)d

故有 a = mc = (y+kx)dc, b = nc = xdc;

可得 gcd(a,b) = gcd((y+kx)dc,xdc) = gcd((y+kx),x)dc  //则 dc 为 a , b 的最大公约数

因 gcd(a,b) = c ; 故 dc = c ; 即 d = 1;

gcd(n,m-kn) = 1;

即 gcd(b,a  mod b) = gcd(n , (m - kn))c = 1 ✖️c = c;

得出结论:a,b的最大公约数 等于 (b与(a除以b的余数) 的最大约数)

 

所以将一块 矩形 土地分为 n块大小相同的正方形时,

可以 先去掉和 短边 一样长度  正方形,

剩下的面积同理,直到剩余图形为矩形~

 

 

 

 

 

D&C的工作原理:

1.找出简单的基线条件;

2.确定如何缩小问题的规模,使其符合基线条件

 

求数组 arr[2,4,6] 的元素总和:

 1.基线条件:

 

2.缩小规模:

 

 

 

 

 

 

 

 

 

这样就缩小了规模~

 

使用递归

(为啥不用循环?请了解下Haskell,不是所有语言都有循环~这语言值得一学~虽然我不会~)

 

快速排序:

 

其运行时间为:O(n log n)

1.基线条件 length<2 当数组只有1个或没有元素时,直接return

2.缩小规模:

  首先从数组选择一个元素,这个元素被称为 基准值(pivot)

  接着,找比 基准值 小的元素以及比 基准值 大的 元素

  这个操作叫做 :分区(partitioning)

现在就拥有了

  1.一个所有元素小于基准值的子数组

  2.一个所有元素大于基准值的子数组

  3.基准值

 这里只是分区,数组还是无序的(如果有序,直接return 1+3+2)

  接着对子数组进行快速排序

归纳证明:

  归纳证明是一种证明算法行之有效的方式,

  分两步:基线条件和归纳条件

 

 

合并排序:

运行 时间为O(n log n)

实际上n是 c*n

c是固定的时间量,被称为常量

对于快速排序,高度依赖于基准值

可分为:平均情况 和 最糟情况

最糟为O(n)  最佳为O(log n)

 

 

 

 

  

posted @ 2020-07-10 23:06  穆乘风  阅读(308)  评论(0)    收藏  举报