时间复杂度分析

简介: 一般情况下,一秒之内相应时间复杂度的算法能解决的数据规模时间复杂度实验如何正确的判断算法的时间复杂度时间复杂度实验:每次将数据规模提高两倍,看时间的变化,以此来验证算法的时间复杂度以下为代码实例:测试算法,分别为二分查找O(logN),查找最大值(O(N)),归并排序(O(NlogN))package com.

img_b59899c3ce7277cdc377bf35124ab43a.png
一般情况下,一秒之内相应时间复杂度的算法能解决的数据规模



时间复杂度实验

如何正确的判断算法的时间复杂度

时间复杂度实验:每次将数据规模提高两倍,看时间的变化,以此来验证算法的时间复杂度

以下为代码实例:

测试算法,分别为二分查找O(logN),查找最大值(O(N)),归并排序(O(NlogN))

package com.ice.time;

import static java.lang.Math.min;

public class MyAlgorithmTester {

    // O(logN),二分法查找
    public static int binarySearch(int arr[], int n, int target) {

        int l = 0, r = n - 1;
        while (l <= r) {
            int mid = l + (r - l) / 2;
            if (arr[mid] == target) return mid;
            if (arr[mid] > target) r = mid - 1;
            else l = mid + 1;
        }
        return -1;
    }

    // O(N),从数组中寻找最大值
    public static int findMax(int arr[], int n) {

        assert (n > 0);

        int res = arr[0];
        for (int i = 1; i < n; i++)
            if (arr[i] > res)
                res = arr[i];

        return res;
    }

    // O(NlogN) 归并排序
    private static void __merge(int arr[], int l, int mid, int r, int aux[]) {

        int i = l, j = mid + 1;
        for (int k = l; k <= r; k++) {
            if (i > mid) {
                arr[k] = aux[j];
                j++;
            } else if (j > r) {
                arr[k] = aux[i];
                i++;
            } else if (aux[i] < aux[j]) {
                arr[k] = aux[i];
                i++;
            } else {
                arr[k] = aux[j];
                j++;
            }
        }
    }

    public static void mergeSort(int arr[],int n){
        int[] aux = new int[n];
        for(int i = 0;i<n;i++){
            aux[i] = arr[i];
        }
        for(int sz = 1;sz<n;sz+=sz){
            for(int i = 0;i<n;i+=sz+sz){
                __merge(arr,i,i+sz-1,min(i+sz+sz-1,n-1),aux);
            }
        }
        return;
    }
}


工具类,生成随机数组或有序数组,用于测试算法

package com.ice.time;

public class MyUtil {

    public static int[] generateRandomArray(int n, int rangeL, int rangeR) {
        assert (n > 0 && rangeL <= rangeR);

        int arr[] = new int[n];

        for (int i = 0; i < n; i++) {
            arr[i] = (int) (Math.random() * (rangeR - rangeL) + rangeL);
        }
        return arr;
    }

    public static int[] generateOrderedArray(int n) {

        int arr[] = new int[n];

        for (int i = 0; i < n; i++) {
            arr[i] = i;
        }
        return arr;
    }
}


Main函数,测试算法用的时间并打印,观察时间就可以推测算法的时间复杂度

package com.ice.time;

import static java.lang.Math.pow;

public class Main {
    public static void main(String[] args){
        for(int i =10;i<=24;i++){
            int n = (int) pow(2,i);
            int[] arr = MyUtil.generateRandomArray(n,0,100000000);

            long startTime=System.currentTimeMillis();
            MyAlgorithmTester.selectionSort(arr,n);
            long endTime=System.currentTimeMillis();//记录结束时间
            
            System.out.print("data size 2^"+i+" = "+n);
            System.out.println("\tTime cost:"+(double)((endTime-startTime)/1000));
        }
    }
}


对于O(logN)的算法,每次数据规模翻两倍,他的时间变化比例:


img_b3745382e9d145a0d42a7aa117f65634.png
大概是一点几倍,当N扩大的非常大时,变化率几乎为0


递归算法的时间复杂度

如果递归中只进行一次递归调用的复杂度分析

典型的例子是递归实现的二分查找,pow函数实现


img_c17aa0b7991ed36a54270f174c8e5449.png

img_8e1562ac0022e8dbfc618bf8d21e94ea.png

在递归中进行多次递归调用的复杂度分析

关注递归调用的次数,使用一颗递归树来看递归调用的次数

img_ed24a6d3d40a55eafbdb3341b14de9d8.png
如果这棵树有N层,那么总调用次数为一个等比数列的和,即2^(n+1)-1,即时间复杂度是一个O(2^n)水平的

那么为什么归并排序一类的递归排序算法,时间复杂度是O(NlogN)呢
原因在于,归并排序的每一层数据规模不变为N,层数实际上是logN


img_2dec0e64f97fa336d2207b3fb22a8d0f.png
递归排序的递归树


递归函数的时间复杂度分析:主定理(涵盖了所有递归情况的复杂度分析)


均摊复杂度分析

对于有些时间复杂度很高的算法,其实他的时间复杂度高是为了降低其他操作的时间复杂度,这时,需要将这个算法的时间复杂度均摊到其他操作上,这就是均摊复杂度。

  • 经典例子:动态数组
  • 复杂度震荡
目录
相关文章
|
存储 关系型数据库 MySQL
终端连接MySQL进行操作(全网超详细的教程,手把手教你)
终端连接MySQL进行操作(全网超详细的教程,手把手教你)
882 0
|
Java Serverless 开发者
Servless 使用体验
在云服务为天下的今天,阿里云发布了ServerLess 函数计算。本文以简单使用Serverless快速入门为主。
1379 1
|
9月前
|
人工智能 自然语言处理 算法
打破AI信息差:2024年20款好用的人工智能工具大盘点
本文带你了解20款值得一试的AI工具,帮助你在内容创作、图像设计、音频视频编辑等领域提高效率、激发创意。
1197 1
打破AI信息差:2024年20款好用的人工智能工具大盘点
|
11月前
|
算法 大数据 Go
Go文件操作:掌握Go的文件读写与操作技巧
本文介绍了Go语言的文件操作功能,包括文件的打开、读写和关闭。Go语言通过`os`和`io`包提供了丰富的文件操作接口,使开发者能够轻松实现文件的读写和管理。文章详细讲解了核心概念、具体操作步骤和代码示例,并探讨了实际应用场景和未来发展趋势。
167 4
|
存储 机器学习/深度学习 移动开发
汇编语言指令系列
汇编语言指令系列
2563 0
|
12月前
|
机器学习/深度学习 数据采集 人工智能
揭开大模型幻觉之谜:深入剖析数据偏差与模型局限性如何联手制造假象,并提供代码实例助你洞悉真相
【10月更文挑战第2天】近年来,大规模预训练模型(大模型)在自然语言处理和计算机视觉等领域取得卓越成绩,但也存在“大模型幻觉”现象,即高准确率并不反映真实理解能力。这主要由数据偏差和模型局限性导致。通过平衡数据集和引入正则化技术可部分缓解该问题,但仍需学界和业界共同努力。
289 4
|
机器学习/深度学习 计算机视觉 Python
【Python 机器学习专栏】图像数据的特征提取与预处理
【4月更文挑战第30天】本文探讨了图像数据的特征提取与预处理在机器学习中的重要性。图像数据具有大容量、信息丰富和冗余性高的特点。特征提取涉及颜色、纹理和形状特征;预处理包括图像增强、去噪和分割。Python的OpenCV和Scikit-image库在处理这些任务时非常有用。常见的特征提取方法有统计、变换和基于模型的方法,而预处理应注意保持图像真实性、适应性调整及验证评估。有效的特征提取和预处理能提升模型性能,Python工具使其更高效。
762 0
|
人工智能 编解码 数据安全/隐私保护
才发现百度自带的AI图片助手这么好用,去水印、画质优化、AI扩图、涂抹消除等功能一应俱全!
才发现百度自带的AI图片助手这么好用,去水印、画质优化、AI扩图、涂抹消除等功能一应俱全!
1708 0
计算机网络实验(华为eNSP模拟器)——第十章 Eth-Trunk(链路聚合)
计算机网络实验(华为eNSP模拟器)——第十章 Eth-Trunk(链路聚合)
计算机网络实验(华为eNSP模拟器)——第十章 Eth-Trunk(链路聚合)
【大模型】如何诊断和解决LLM 开始生成令人反感或与事实不符的输出?
【5月更文挑战第7天】【大模型】如何诊断和解决LLM 开始生成令人反感或与事实不符的输出?