算法时间复杂度与对数器

认识时间复杂度

常数时间的操作:一个操作如果和数据量没有关系,每次都是固定时间内完成的操作,叫做常数操作。

常数时间的操作符合两点:

  1. 一次操作的时间与数量级没有关系。
  2. 每次操作花费的时间是确定有限的。

时间复杂度为一个算法流程中,常数操作数量的指标。常用O(读作bigO)来表示。具体来说,在常数操作数量的表达式中,只要高阶项,不要低阶项,也不要高阶项的系数,剩下的部分如果记为f(N),那么时间复杂度为O(f(N))。

如果一个算法的时间复杂度是 a*N^2 + b*N + c,那么 a*N^2 就是高阶项,b*N为低阶项,c为常数项。不要低阶项就是抛除 b*N + c ,只留下最高阶 a*N^2;也不要高阶项的系数就是抛除系数a,最后的结果为 N^2,所以这个算法的时间复杂度为 O(N^2)。

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

常用的时间复杂度按照耗费的时间从小到大依次是:

O(1)<O(logn)<O(n)<O(nlogn)<O(n²)<O(n³)<O(2ⁿ)<O(n!)

对数器的概念和使用

对数器是用来测试代码正确性的,我们在找不到合适的oj系统测试自己的代码时,可以自己写一个对数器对代码进行测试。

1,有一个你想要测的方法A

比如我写了一个排序算法A,需要检测是否正确。

    public static void bubbleSort(int[] arr){
        if(arr == null || arr.length == 0){
            return;
        }
        for(int end = arr.length - 1; end > 0; end--){
            for(int i = 0; i < end; i++){
                if(arr[i] > arr[i + 1]){
                    int temp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = temp;
                }
            }
        }
    }

2,实现一个绝对正确但是复杂度不好的方法B

这里使用系统的排序算法保证算法的正确性。

    public static void comparator(int[] arr) {
        Arrays.sort(arr);
    }

3,实现一个随机样本产生器

这个方法产生一个最大长度maxSize和最大值maxValue的随机数组,作为一次随机样本。

    public static int[] generateRandomArray(int maxSize, int maxValue) {
        int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
        }
        return arr;
    }   

4,实现比对的方法

对比我需要检测的方法A和绝对正确的方法B所产生的结果是否相同。

    public static boolean isEqual(int[] arr1, int[] arr2) {
        if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
            return false;
        }
        if (arr1 == null && arr2 == null) {
            return true;
        }
        if (arr1.length != arr2.length) {
            return false;
        }
        for (int i = 0; i < arr1.length; i++) {
            if (arr1[i] != arr2[i]) {
                return false;
            }
        }
        return true;
    }

5,把方法A和方法B比对很多次来验证方法A是否正确。

采取大量随机样本对比,这里使用了50万个随机样本进行对比。

    public static void main(String[] args) {
        int testTime = 500000;
        int maxSize = 100;
        int maxValue = 100;
        boolean succeed = true;
        for (int i = 0; i < testTime; i++) {
            int[] arr1 = generateRandomArray(maxSize, maxValue);
            int[] arr2 = copyArray(arr1);
            bubbleSort(arr1);
            comparator(arr2);
            if (!isEqual(arr1, arr2)) {
                succeed = false;
                break;
            }
        }
        System.out.println(succeed ? "Nice!" : "Fucking fucked!");

        int[] arr = generateRandomArray(maxSize, maxValue);
        printArray(arr);
        bubbleSort(arr);
        printArray(arr);
    }

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

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

递归行为的时间复杂度

递归的本质就是用压栈与出栈操作。

当递归操作需要执行子递归操作时,会将当前执行的所有数据压入栈中,这些数据包括当前跑到多少行,当前的参数和函数内的参数变量等等。

当子递归操作返回时进行出栈操作,然后读取出栈后栈顶空间的信息,也就是返回到当初调用的地方。

递归行为时间复杂度的计算

一般的空间复杂度可以使用master公式计算:

master公式 : T(N) = a * T(N / b) + O(N ^ d)

T(N):父问题的样本量
a:调用模块发生的次数
T(N/b):子问题的样本量
O(N^d):除去子问题调用过程外,剩下部分的时间复杂度

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

我们使用递归二分求最大数来举例:

    /*
     * 递归二分求最大数
     */
    public static int getMaxNum(int[] arr, int L, int R) {
        // 递归结束条件:只剩下一个数
        if(L == R)
            return arr[L];

        int mid = L +((R - L) >> 1);  //位运算取中值
        int leftMax = getMaxNum(arr, L, mid);  //T(N/2)
        int rightMax = getMaxNum(arr, mid + 1, R);  //T(N/2)

        return Math.max(leftMax, rightMax);  //O(1)
    }    

递归边界:当整个数组被分割成只有一个数时结束递归。

递归逻辑:将数组从中间分割为两个数组,分别取出左右两个数组的最大值,再对比这两个值取最大值。而分割出来的每个数组又继续分割为两个数组,直到分割出来的数组只有一个数为止。

递归时间复杂度的计算:

master公式:T(N) = a * T(N / b) + O(N ^ d)

a:调用模块发生的次数,这里左右两边各执行了一次,a = 2;

b:T(N/b)为子问题的样本量,数组从中间分为相等两份,b = 2;

d:O(N^d)为剩下部分的时间复杂度,这里只执行了取中间值和比较最大值的两个操作,都为常数操作,d = 0;

套用公式以后:T(N) = 2 * T(N / 2) + O(N ^ 0)

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

时间复杂度即为:O(N^1) = O(N)

参考资料:牛客网左程云初级算法教程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,692评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,482评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,995评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,223评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,245评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,208评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,091评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,929评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,346评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,570评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,739评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,437评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,037评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,677评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,833评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,760评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,647评论 2 354

推荐阅读更多精彩内容

  • 声明:本笔记所涉及的资料来源于牛客网 认识时间复杂度 常数时间的操作:一个操作如果和数据量没有关系,每次都是固定时...
    WangGavin阅读 631评论 0 0
  • 算法复杂度 时间复杂度 空间复杂度 什么是时间复杂度 算法执行时间需通过依据该算法编制的程序在计算机上运行时所消耗...
    KODIE阅读 3,256评论 0 9
  • #Eric爱分享-1分钟职场智慧# 有三个军官,接到实弹演练的命令,准备整装出发。领导就问他们有没有什么要求,现在...
    行业观察小朋友阅读 187评论 0 0
  • 迎七一,洛新卫生院支部开展了一系列提高党性认识的活动。首先李院长讲了以“如何增强四个意识,争做一名合格党员...
    QHR阅读 223评论 0 0
  • 说出来有些人可能觉得很可笑,可是最近一年我确实一直在思考人生的意义到底是什么?我要做些什么,有没有属于我的使命?因...
    hello_yolanda阅读 701评论 0 0