IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【数据结构】初识集合框架、时间和空间复杂度 -> 正文阅读

[数据结构与算法]【数据结构】初识集合框架、时间和空间复杂度

1.1.集合框架简介

官方教程
集合框架用于存储数据的容器。
Java 集合框架Java Collection Framework又被称为容器 container ,是定义在 java.util 包下的一组接口 interfaces
和其实现类 classes 。

1.2. 数据结构

数据结构是计算机存储和组织数据的方式,互相之间存在一种或多种特定关系的数据元素的集合。

  • 🟠类和接口:
    在这里插入图片描述
  • Collection:是一个接口,包含了大部分容器常用的一些方法。
  • List:是一个接口,规范了ArrayList 和 LinkedList中要实现的方法。
    • ArrayList:实现了List接口po,底层为动态类型顺序表。
  • LinkedList:实现了List接口,底层为双向链表。
  • Stack:底层是栈,栈是一种特殊的顺序表。
  • Queue:底层是队列,队列是一种特殊的顺序表。
  • Deque:是一个接口。
  • Set:集合,是一个接口,里面放置的是K模型
  • HashSet:底层为哈希桶,查询的时间复杂度为O(1)
  • TreeSet:底层为红黑树,查询的时间复杂度为O( log ? 2 N \log_2N log2?N),关于key有序的。
  • Map:映射,里面存储的是K-V模型的键值对
    • HashMap:底层为哈希桶,查询时间复杂度为O(1)。
    • TreeMap:底层为红黑树,查询的时间复杂度为O( log ? 2 N \log_2N log2?N),关于key有序。

注释:

  • O( log ? 2 N \log_2N log2?N):以2为底多少次方等于N,一般写成O(logN),表示的就是O( log ? 2 N \log_2N log2?N)。

1.3. 数组和集合的区别

数组和集合的区别:

  • 数组是固定长度的;集合可变长度的。
  • 数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型。
  • 数组存储的元素必须是同一个数据类型;集合存储的对象可以是不同数据类型。

2. 时间和空间复杂度

2.1 算法效率

算法(Algorithm):就是定义良好的计算过程,他取一个或一组的值为输入,并产生出一个或一组值作为输出。简单来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果,而算法效率就是根据每一条语句执行的次数和产生的空间大小来估算出一个程序的效率。

  • 算法效率分为两种
    - 时间效率:也被称为时间复杂度,主要用来衡量一个算法的运行速度
    - 空间效率:也被称为空间复杂度,主要用来衡量一个算法所需要的额外空间

在计算机发展的早期,计算机的存储容量很小,所以对空间复杂度很是关注,但是经过计算机行业的迅速发展,如今的存储容量已经达到很高的程度,比如512GB、1TB已经不再像从前那么罕见了, 所以我们现在更加关注一个算法的时间复杂度

2.2 时间复杂度

时间复杂度说一个数学函数,一个算法所花费的时间与程序中语句的执行次数成正比,我们编译的算法基本操作次数,为算法的时间复杂度
在这里插入图片描述

大O渐进表示法

在这里插入图片描述
func()函数基本操作的次数: F(N)=N^2+2*N+10

  • N = 10 : F(N) =130 。
    • F(N) = 10^2+2*10+10 = 130。
  • N = 100 : F(N) = 10210。
  • N = 1000 : F(N) = 1002010。

实际上我们只需要大概的执行次数,那么我们应该用大O的渐进表示法。

  • 大O符号(Big O notation):是用于描述函数渐进行为的数学符号。

推导大O 阶方法:F(N)=N^2+2*N+10

  1. 用常数1取代运行时间中的所有加法常数。(F(N)=N^2+2*N+1。)

  1. 修改后的运行次数函数中,只保留最高阶项。(F(N)=N^2 +2*N+1。)

  1. 如果最高阶项存在且不是1,则去除这个项相
    乘的常数,得到的结果就是大O阶。(eg:10*N2, 去除10,只保留N2)

使用大O阶的渐进表示法后,func()函数的时间复杂度为:O(N2)。

  • 时间复杂度有最好、最坏、平均之分:
  1. 最好的情况:程序运行最少的次数。(下限)
  2. 最坏的情况:程序运行最多的次数。(上限)
  3. 平均情况:程序期望的运行次数。
	int[] arr = {1,23,5,6,7,8,9,10};
	int targer = 9;
for (int j = 0; j < arr.length; j++) {
          if(arr[i] == target){
          		return;
          }
 }
  • 例如:在一个为N个数组长度中查找一个数据target。
    • 最好的情况:数组一个元素就是target,1次找到。
    • 最坏的情况:数组最后一个元素说target,N次找到。
    • 平均的情况:N/2次找到。

在一般情况下关注的说算法最坏的运行情况,所以数组查找一个元素的时间复杂度为O(N)。

  • 常见的时间复杂度量级
    • 常数阶O(1)
    • 对数阶O(logN)
    • 线性阶O(n)
    • 线性对数阶O(nlogN)
    • 平方阶O(n2)
    • 立方阶O(n3)
    • K次方阶O(nk)
    • 指数阶(2n)

上面从上至下依次的时间复杂度越来越大,执行的效率越来越低

时间复杂度练习题

  • 例题1
   // 计算func2的时间复杂度? 
    public void func2 ( int N){
        int count = 0;
        for (int k = 0; k < 2 * N; k++) {
            count++;
        }
        int M = 10;
        while ((M--) > 0) {

            count++;
        }
        System.out.println(count);
    }

解题:实例1基本操作执行了2N+10次,通过推导大O阶方法知道,时间复杂度为 O(N)

  • 例题2
  // 计算func3的时间复杂度? 
    void func3(int N, int M) { 
        int count = 0; 
        for (int k = 0; k < M; k++) {
              count++; 
        }
        for (int k = 0; k < N ; k++) {
            count++; }System.out.println(count);
        
    }

解题: 实例2基本操作执行了M+N次,有两个未知数M和N,时间复杂度为 O(N+M)

  • 例题3
 // 计算func3的时间复杂度?
    public void func4(int N) {
        int count = 0;
        for (int k = 0; k < 100; k++) {
            count++; }System.out.println(count);
    }

解题:实例3基本操作执行了100次,通过推导大O阶方法,时间复杂度为 O(1)。

  • 例题4
  // 计算bubbleSort的时间复杂度? 
    void bubbleSort(int[] array) { 
        for (int end = array.length; end > 0; end--) {
            boolean sorted = true;
            for (int i = 1; i < end; i++) { 
                    if (array[i - 1] > array[i]) { 
                          Swap(array, i - 1, i);
                          sorted = false; 
                    }
            }
            if (sorted == true) {
                break;
            }
        } 
    }

**解题:*实例4基本操作执行最好N次,最坏执行了(N(N-1))/2次,通过推导大O阶方法+时间复杂度一般看最坏,时间复杂度为 O(N2)

  • 例题5
// 计算binarySearch的时间复杂度?
    int binarySearch(int[] array, int value) {
        int begin = 0;
        int end = array.length - 1;
        while (begin <= end) {
            int mid = begin + ((end-begin) / 2);
            if (array[mid] < value){
                begin = mid + 1;
            } else if (array[mid] > value) {
                end = mid - 1;
            }else{
                return mid;

            }
        }
        return -1;
    }

解题: 实例5基本操作执行最好1次,最坏 次 log ? 2 N \log_2N log2?N,时间复杂度为 O( log ? 2 N \log_2N log2?N)
ps log ? 2 N \log_2N log2?N 在算法分析中表示是底数为2,对数为N,有些地方会写成lgN(文章前段已经讲解了)。(二分查找每次排除掉一半的不适合值,一次二分剩下:n/2两次二分剩下:n/2/2 = n/4。二分查找的时间复杂度为O( log ? 2 N \log_2N log2?N ))

  • 例题6
  // 计算阶乘递归factorial的时间复杂度?
    long factorial(int N) { 
        return N < 2 ? N : factorial(N-1) * N;
    }

解题: 实例6通过计算分析发现基本操作递归了N次,时间复杂度为O(N)。

  • 例题7
  // 计算斐波那契递归fibonacci的时间复杂度?
    int fibonacci(int N) {
        return N < 2 ? N : fibonacci(N-1)+fibonacci(N-2);
    }

解题: 实例7通过计算分析发现基本操作递归了2N次,时间复杂度为O(2N )。(建议画图递归栈帧的二叉树理解)

3.时间复杂度

时间复杂度表示的说临时占用存储空间大小的量度。也可以使用大O的渐进表示法。

  • 空间复杂度比较常用的有:O(1)、O(n)、O(n2)。

时间复杂度O(1):
使用了常数个额外空间,所以空间复杂度为O(1)。

    // 计算bubbleSort的空间复杂度?
    void bubbleSort2(int[] array) {
        for (int end = array.length; end > 0; end--) {//int end 开辟1个空间
            boolean sorted = true;//开辟1个空间
            for (int i = 1; i < end; i++) {//int i 开辟1个空间
                if (array[i - 1] > array[i]) {
                    Swap(array, i - 1, i);
                    sorted = false;
                }
            }
            if (sorted == true) {
                break;
            }
        }
    }

时间复杂度O(N):动态开辟了N个空间,空间复杂度为 O(N)

       // 计算fibonacci的空间复杂度?
       public int[] fibonacci2(int n) {
           int[] fibArray = new int[n + 1];//开辟了N+1个空间
           fibArray[0] = 0;
           fibArray[1] = 1;
         for (int i = 2; i <= n ; i++) {//int i  开辟一个空间
            fibArray[i] = fibArray[i - 1] + fibArray [i - 2];
        }
        return fibArray;
    }
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-09-25 23:20:35  更:2022-09-25 23:22:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:29:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码