【第一章】(2)算法时间复杂度【重点】和空间复杂度分析

给定一个查询算法代码,实现如下:

    /**
     * 线性查找
     *
     * @param a      数组
     * @param target 查找目标
     * @return 目标在数组中的索引,没有就返回 -1
     */
    public static int linerSearch(int[] a, int target) {
        for (int i = 0; i < a.length; i++) {
            if (a[i] == target) {
                return i;
            }
        }
        return -1;
    }

和二分查找进行比较,时间复杂度的算法 (O)

/**
     * 和二分查找做比较,采用事前分析方法【假设执行每一行代码的时间相同】。当 数组 a 中有 n 个数据
     * 1、最坏的情况,没有找到数据
     *    【linerSearch】没有找到数据,代码全部执行,代码的执行次数分别是:
     *    int i = 0;            1
     *    i < a.length;         n + 1(最后一次比较)
     *    i++                   n
     *    a[i] == target        n
     *    return -1;            1
     *
     *    那么一共执行次数就是      3*n + 3 可以发现 执行次数 和 n 成一次函数线性相关。
     *
     *    看【binarySearchBasic】 没有找到数据
     *    在二分查找中,因为正数时向下取整,所以当右侧没有找到时用时会多一些。
     *    例如在 [2,6,7,8,9,12,13,45] 中 ,查找 50 的循环次数一定比查找 1 执行的代码行数多。
     *
     *    int i = 0, j = a.length - 1;                           2
     *    return -1;                                             1
     *         元素个数        循环次数
     *         4 - 7            3       log_2(4) = 2
     *                                  log_2(7) = 2.xxx 向下取整即可
     *         8 - 15           4       log_2(8) = 3
     *         16 - 31          5       log_2(16) = 4
     *         32 - 63          6       log_2(32) = 5
     *         ...
     *         可以发现元素个数和循环次数是一个以 2 为底的对数关系 ;循环系数 = log_2(元素个数) + 1
     *
     *         那么循环次数(L) = floor(log_2(n)) + 1;floor 函数表示向下取整数
     *
     *    i <= j;                                                L + 1
     *    int m = (i + j) >>> 1;                                 L
     *    target < a[m]                                          L
     *    a[m] < target                                          L
     *    i = m + 1;                                             L
     *
     *    总次数: 5 * L + 4 = 5 * [floor(log_2(n)) + 1] + 4
     *
     *   现在就可以做比较了。设每一行代码执行时间为 t
     *   当数组有 4 个元素时:
     *      线性查找:[3*n + 3] * t = 15t
     *      二分查找:[5 * [floor(log_2(n)) + 1] + 4] * t = 19t
     *      在数据量小的时候,线性查找还有优一些
     *
     *   当数据元素是 1024 时:
     *      线性查找:3 * 1024 + 3 = 3075 t
     *      二分查找:5 * (10 + 1) + 1 + 4 = 55 t
     *      当数据量大的时候,差别就非常大了。
     *
     *
     *
     * 时间复杂度:一个算法的执行,随着数据规模的变大,而增长的时间成本
     *    时间复杂度不依赖于环境因素【硬件环境和软件环境】
     *
     * 时间复杂度如何体现呢?
     *    假设算法要处理的数据规模是 n,代码执行行数用 f(n) 表示。
     *      线性查找:f(n) = 3 * n + 3;
     *      二分查找:f(n) = 5 * [floor(log_2(n)) + 1] + 4
     *    为了更加直观的看出 f(n) ,可以对齐进行简化,让真实和化简后的函数结果近似,就用基于 O 表示
     *    按照求极限的方式当 n -> 正无穷大时,保留一项即可。 可以将常数和系数全部省略。
     *        3 * n + 3 ~ n ~ O(n)
     *        5 * [floor(log_2(n)) + 1] + 4 ~  log_2(n) ~ O(log_2(n)) ~ O(log(n))
     *
     *    常见的时间复杂度:
     *       1、O(1):常量级,最优的时间复杂度
     *       2、O(log(n)):对数时间,和底数没有关系
     *       3、O(n):线性时间
     *       4、O(n*log(n)):拟线性时间,和 O(n) 差不多
     *       5、O(n^2):平方时间
     *       6、O(2^n):指数时间
     *       7、O(n!):阶乘时间
     *       8、O(n^n):时间复杂度最差。
     *
     *    效率排序:O(1) < O(log(n)) < O(n) < O(n*log(n)) < O(n^2) < O(2^n) < O(n!) < O(n^n)
     *
     *
     */

空间复杂度:和时间复杂度类似,一般也使用 O 表示:一个算法执行随着数据规模的变大,从而增长的额外空间成本。

说明:在大多数情况下,都考虑牺牲空间复杂度从而优化时间复杂度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值