算法(一)


插入排序

适用于少量元素的排序,思想和排序扑克牌一样:一张张地抽取,然后和手中已经排好序的最大的牌进行比较,大之则插入右边,小之则和它的前一张牌比较。
伪代码:

//[1,j-1]是手中牌,[j,A.length]是待插入的牌
for j = 2 to A.length  //从待插入的第二张开始,A[1]表示第一张已经抽在手中的牌
    key = A[j]
    i = j - 1  //得到手中牌的数
    while i > 0 and A[i] > key //从手中最大的牌开始比较
        A[i+1] = A[i] //大于时,向当前位置的下一张移位
        i = i-1 //取当前位置的前一位进行比较
    A[i+1] = key //从前一位回到当前位置进行插入

时间复杂度为O(n^2)

随机访问机器RAM,没有并发操作,指令一条接一条地执行。

归并排序(分治法排序)

使用分治法实现,思想:将扑克牌分成2份已经排好序的堆,从上到下按从小到大放好,然后从2堆牌的顶层开始相互比较,拿出较小的那张,以此直到一方或双方没有牌了,就将剩下的直接合并。递归:将分成的2份继续分成2份,直到只剩下1张牌,然后和同等级的牌进行一对一地比较,取出较小的一张放在顶层。
伪代码:
合并(A,p,q,r):

//p开始位置,r结束位置,q分界点
n1 = q - p + 1
n2 = r - q
for i = 1 to n1
    L[i] = A[p + i -1]
for j = 1 to n2
    R[i] = A[q + j]
L[n1+1] = 标志
R[n2+2] = 标志
i = 1
j = 1
for k = p to r
    if L[i]<=R[j]
       A[k] = L[i]
       i = i + 1
    else
       A[k] = R[j]
       j = j + 1

递归(A,p,r):

if p < r
    q = (p+r)/2(取下界)
    递归(A,p,q)
    递归(A,q+1,r)
    合并(A,p,q,r)

时间复杂度为nlgn。

分治:将规模为T(n)的问题分解为a个规模为原问题规模1/b的子问题,设D(n)为分解所需时间,C(n)为合并所需时间,当规模大于1时,递归表达式如下。
T(n) = aT(n/b) + D(n) + C(n)

  • 渐进符号
    f(n) = O(g(n)) 类似于 a<=b
    f(n) = Ω(g(n)) 类似于 a>=b
    f(n) = θ(g(n)) 类似于 a=b
    f(n) = o(g(n)) 类似于 a< b
    f(n) = w(g(n)) 类似于 a>b

分治策略

3个步骤:
分解:将问题分解为一些规模更小但是本质一样的子问题
解决:如果子问题的规模足够小,则停止递归,直接求解
合并:将子问题的解组合成原问题的解
一般和递归一起使用:先列出递归式,然后根据递归式设计算法。

分治法求解具有最大和的子数组

问题:给出一个值为实数的数组,求解具有最大和的连续的子数组。比如股票投资求出最佳的买入时间和卖出时间。
思想:将数组递归地分成相同量的2份,分别求出左边数组的最大和,右边数组的最大和,然后求出跨中间点的数组最大和,然后将3个最大和进行比较,取最大的那个就是整个数组的最大和子数组。
伪代码:
跨中间点最大子数组(A,low,mid,high)

leftsum = 负无穷
sum = 0
for i = mid downto low  //从中间向2边取值相加
    sum = sum + A[i]
    if sum > leftsum
        leftsum = sum
        maxleft = i  //记录最大处的下界
rightsum = 负无穷
sum = 0
for j = mid + 1 to high
    sum = sum + A[j]
    if sum > rightsum
        rightsum = sum
        maxright = j  //记录最大处的上界
return (maxleft,maxright,leftsum + rightsum)  //(下界,上界,和)

递归(A,low,high)

if high == low
    return (low,high,A[low])
else mid = (low + high)/2  //取下界
    (leftlow,lefthigh,leftsum) = 递归(A,low,mid)
    (rightlow,righthigh,rightsum) = 递归(A,mid+1,high)
    (crosslow,crosshigh,crosssum) = 跨中间点最大子数组(A,low,mid,high)
    if leftsum >= 其他2return (leftlow,lefthigh,leftsum)
    elseif rightsum >= 其他2return (rightlow,righthigh,rightsum)
    else return (crosslow,crosshigh,crosssum)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值