算法基础--第一章--认识复杂度和简单排序算法

回顾一下算法方面的基础知识

-- 时间复杂度和空间复杂度 选择排序、冒泡排序、插入排序的细节和时间复杂度分析
-- 二分法的使用和复杂度分析
-- 一道时间复杂度很低的利用异或运算解决的问题
-- 常见时间复杂度的比较
-- 详解递归函数与常见递归函数的复杂度估算(master公式)
--详解对数器的使用

认识时间复杂度

常数操作(与数据量没有关系,固定时间):数组寻址操作(内存跳一下时间),加减乘除(整型32位),位运算

时间复杂度:一个算法流程中常数操作数量的指标。

(M*N)*O(1):2个for循环的遍历

(aN^{2}+bN+1)*O(1)  : O(N^{2}):只要高阶项,不要低阶项,也不要高阶项的系数,剩下的记为f(N),时间复杂度为O(f(N)).

评价算法的指标:先看时间复杂度的指标,然后再分析不同数据样本下的实际运行时间,也就是常数项时间。

二分O(log_{2}N)

[二分法通常用于二分查找。所谓二分,其实就是每次与有序序列中的中值比较,如果比中值小,则去中值的左边序列中查找,如果比中值大,则去中值的右边序列中查找,如果与中值相等,则查找成功。就这样按照上面的步骤循环查找,直到找到或者序列长度为1为止。]

冒泡: 算法思想就是气泡往上冒的样子,2个2个比较,冒一次排好一个数,再冒第二次...O(N^{2})

[在长度为n的序列中,每次遍历整个序列,比较前后两个元素,如果后面的这个元素比前面的这个元素小,交换两个元素,这样多次遍历后,知道序列有序。]

选择:第1趟,在待排序记录r[1]~r[n]中选出最小的记录,将它与r[1]交换;第2趟,在待排序记录r[2]~r[n]中选出最小的记录,将它与r[2]交换;以此类推,第i趟在待排序记录r[i]~r[n]中选出最小的记录,将它与r[i]交换,使有序序列不断增长直到全部排序完毕O(N^{2})

[在长度为n的序列中,每次遍历n-i次序列,(i=0,1,2,... ,n)将序列后(n-i)个元素中最大/小的元素放到第i个位置上。]

插入排序:扑克牌整牌,抽到一张牌,排序

插入排序与数据状况有关系,冒泡和选择与数据状况无关系。插入在有序下O(N),无序O(N^{2})

[在长度为n的序列中,将序列第 i 个元素有序地插入到前(i-1)个已经有序的元素中,直到序列有序。]

 

一道时间复杂度很低的利用异或(^)运算解决的问题:

整数型数组中,每个元素均出现两次,除了一个元素例外,如何找出这个元素?能否设计一个线性时间的算法,且不需要额外的存储空间?

使用异或运算符(^)可以O(n)的时间复杂度解决这个问题。

异或运算符的特点是:数a两次异或同一个数b(a=a^b^b)仍然为原值a。对于任何数x,都有x^x=0,x^0=x。

其实O(n)的算法不容易一下子想到,先说说常规的解决思路,有如下两种:
            1、对元素的出现次数进行统计,可进行n*n循环,判断元素是否只出现了一次。这样时间复杂度为O(n^2), 不需要额外空间。
            2、先对元素进行排序,然后进行相邻两元素的对比,如a1和a2对比,a3和a4对比,如果不同,则前一个元素(a1、a3)就是所要查找的元素。这样的时间复杂度还是比O(n)高。

这两种解法的时间复杂度都比O(n)更高。但是,如果你运用了异或运算符的特点,那么这个问题就很容易解决了,算法复杂度为O(n),且不需要额外空间,像这样:
 

int singleNumber(int A[], int n) {
    int result = 0;
    for (int i = 0; i<n; i++)
    {
        result ^=A[i];
    }
    return result;
}

 

对数器的概念和使用

(大数组,贪心策略)

0.有一个你想要测的方法a,

1.实现一个绝对正确但是复杂度不好的方法b

2.实现一个随机样本产生器

3.实现比对的方法

4.把方法a和方法b比对很多次来验证方法a是否正确。

5.如果有一个样本使得比对出错,打印样本分析是哪个方法出错

6.当样本数量很多时比对测试依然正确,可以确定方法a已经正确

 

额外空间复杂度:为完成算法额外申请的空间

 

递归行为及时间复杂度:系统栈

任何递归可以改为非递归

master公式:

T(N)= aT(\frac{N}{b})+O(N^{d})

T(n/b):子过程样本量  a:子过程几次  n^d:剩下的过程

1) log(b,a) > d -> 复杂度为O(N^log(b,a))

2) log(b,a) = d -> 复杂度为O(N^d * logN)

3) log(b,a) < d -> 复杂度为O(N^d)

 

归并排序的细节与复杂度分析

时间复杂度O(N*logN),额外空间复杂度O(N)

左右侧分别排序,整体外排。

5 3 6 | 2 0 1  -->  3 5 6 | 0 1 2  准备辅助数组外排

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

 

小和问题和逆序对问题(归并排序解决)

小和问题
在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组的小和。
例子:
[1,3,4,2,5]
1左边比1小的数,没有;
3左边比3小的数,1;
4左边比4小的数,1、3;
2左边比2小的数,1;
5左边比5小的数,1、3、4、2;
所以小和为1+1+3+1+1+3+4+2=16

1 3 4 | 2 5

当前数是cur,右侧有多少数比当前数大 x个cur

\frac{L+R}{2}      L + (R-L) >> 1 不会溢出且 速度快(位运算比算数运算快)

 

逆序对问题
在一个数组中,左边的数如果比右边的数大,则折两个数构成一个逆序对,请打印所有逆序对。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值