数据结构与算法 java描述 笔记

第一章 算法及其复杂度

算法的定义

​ 在特定计算模型下,在信息处理过程中为了解决某一类问题而设计的一个指令序列。

要素

  • 输入:待处理的信息,即对具体问题的描述。
  • 输出:经过处理之后得到的信息,即问题的答案
  • 确定性:任一算法都可以描述为由若干种基本操作组成的序列。
  • 可行性:在相应的计算模型中,每一基本操作都可以实现,且能够在常数时间内完成。
  • 有穷性:对于任何输入,按照算法,经过有穷次基本操作都可以得到正确的输出。

算法性能的分析与评价

问题规模、运行时间及时间复杂度

​ 为了简化分析,我们通常只考虑输入规模这一主要因素。

​ 如果将某一算法为了处理规模为 n 的问题所需的时间记作 T(n),那么随着问题规模 n 的增长,运行时间 T(n)将如何增长?我们将 T(n) 称作算法的时间复杂度

渐进复杂度

​ 在评价算法的运行时间时,我们往往可以忽略其在处理小规模问题时的性能,转而关注其在处理足够大规模问题时的性能,即所谓的渐进复杂度(Asmpototic complexity)。

大 O 记号

​ 如果存 在正常数 a、N 和一个函数 f(n),使得对于任何 n > N,都有

​ T(n) < a × f(n)

​ 我们就可以认为在 n 足够大之后,f(n)给出了 T(n)的一个上界。

​ 对于这种情况,我们记之为 T(n) = O(f(n)) 这里的 O 称作“大 O 记号(Big-O notation)”。

大Ω记号

​ 如果存在正常数 a、N 和一个函数 g(n),使得对于任何 n > N,都有

​ T(n) > a × g(n)

​ 我们就可以认为在 n 足够大之后,g(n)给出了 T(n)的一个下界。

​ 对于这种情况,我们记之为 T(n) = Ω(g(n)) 这里的Ω称作“大Ω记号(Big-Ω notation)”。

Θ记号

​ 如果存在正常数 a N,都有

​ a × h(n) < T(n) < b × h(n)

​ 我们就可以认为在 n 足够大之后,h(n)给出了 T(n)的一个确界。

​ 对于这种情况,我们记之为 T(n) = Θ(h(n)) Θ记号是对算法执行效率的一种准确估计⎯⎯对于规模为 n 的任意输入,算法的运行时间都与 Θ(h(n))同阶。

空间复杂度

​ 算法所需使用的存储空间量,即算法空间复杂度

​ 就渐进复杂度的意义而言,在任何一个算法的任何一次运行过程中,其实际占用的存 储空间都不会多于其间执行的基本操作次数。

​ 引入时间复杂度的各种记号来度量算法的空间复杂度。

算法复杂度及其分析

O(1)⎯⎯取非极端元素

问题:给定整数子集S, +∞ > |S| = n ≥ 3,从中找出一个元素 a∈S,使得 a ≠ max(S)a ≠ min(S)。也就是说,在最大、最小者之外,取出任意一个数。

算法:NonextremeElement(S[], n)
输入:由n个整数构成的集合S
输出:其中的任一非极端元素
{
任取的三个元素x, y, z ∈ S; //既然S是集合,这三个元素必互异
通过比较,找出其中的最小者min{x, y, z}和最大者max{x, y, z};
输出最小、最大者之外的那个元素;
}

思路:

S 是有限集,故其中的最大、最小元素各有且仅有一个。

因此,无论 S 的规 模有多大,在前三个元素 S[0]、S[1]和 S[2]中,必包含至少一个非极端元素。

我们可以取 x = S[0]、y = S[1]和 z = S[ 2],这只需执行三次基本操作,耗费 O(3)时间。

为了确定这三个元 素的大小次序,我们最多需要做三次比较(请读者自己给出证明),也是 O(3)时间。

最后,输出居中 的那个元素只需 O(1)时间。

运行时间为: T(n) = O(3) + O(3) + O(1) = O(7) = O(1)

O(logn)⎯⎯进制转换

问题:给定任一十进制整数,将其转换为三进制表示。比如

​ 23(10) = 212(3)

​ 101(10) = 10202(3)

算法:BaseConversion(n)
输入:十进制整数n
输出:n的三进制表示
{
不断循环,直到n = 0 {
输出 n % 3; //取模
令 n = n/3; //整除
}
}

以 101(10)为例思路:

​ 第一轮循环,输出 101 mod 3 = 2,n = 100/3 = 33; 2

​ 第二轮循环,输出 33 mod 3 = 0,n = 33/3 = 11; 0

​ 第三轮循环,输出 11 mod 3 = 2,n = 11/3 = 3; 2

​ 第四轮循环,输出 3 mod 3 = 0,n = 3/3 = 1; 0

​ 第五轮循环,输出 1 mod 3 = 1,n = 1/3 = 0。 1

​ result=10202(3)

该算法由若干次循环构成, 每一轮循环内部,都只需进行两次基本操作(取模、整除)。

每经过一轮循环,n都至少减少至 1/3。于是,至多经过

\[1+[log3n]
\]

次循环,即 可减小至 0。

因此,该算法需要运行 O(2×(1+[log3n])) = O(log3n)时间。

鉴于大 O 记号的性质,我们通常会忽略对数函数的常底数。比如这里的底数为常数 3,故通常 将上述复杂度记作 O(logn)。

O(n)⎯⎯数组求和

问题:给定n个整数,计算它们的总和。

算法:Sum(A[], n)
输入:由n个整数组成的数组A[]
输出:A[]中所有元素的总和
{
令s = 0;
对于每一个A[i],i = 0, 1, …, n-1
令s = s + A[i];
输出s;
}

思路

对s的初始化需要O(1)时间。

每一轮循环中只需进行一次累 加运算,这属于基本操作,可以在O(1)时间内完成。

O(1) + O(1)×n = O(n+1) = O(n)

O(n\(^2\) )⎯⎯起泡排序

问题:冒泡排序

算法:Bubblesort(S[], n)
输入:n个元素组成的一个序列S[],每个元素由[0..n-1]之间的下标确定,元素之间可以比较大小
输出:重新调整S[]中元素的次序,使得它们按照非降次序排列
{
从S[0]和S[1]开始,依次检查每一对相邻的元素;
只要它们位置颠倒,则交换其位置;
反复执行上述操作,直到每一对相邻元素的次序都符合要求;
}

思路:

为了对n个整数排序,该算法的外循环最多需要做n轮。

经过第i轮循环,元素 S[n-i-1]必然就位,i = 0, 1, …, n-1。\(r\)

在第i轮外循环中,内循环需要做n-i-1 轮。

在每一轮内循环中, 需要做一次比较操作,另外至多需要做三次赋值操作,这些都属于基本操作,可以在O(4)的时间内 完成。

\[T(n) = \sum_{i=0}^{n-1} {(n-i-1)} × O(4) = O(2n(n-1)) = O(2n^2–2n)
\]
\[
\]

鉴于大 O 记号的特性,低次项可以忽略,常系数可以简化为 1,故再次得到 T(n) = O(n^2 )

O(2\(^r\) )⎯⎯幂函数

问题:虑幂函数的计算

算法:PowerBruteForce(r)
输入:非负整数r
输出:幂2^r
{
power = 1;
while (0 < r--)
power = power * 2;
return power;
}

共需要做r次迭代,每次迭代只涉及常数次基本操作,故总共需要运行O(r)时间。

问题的输入规模为n,故有O(r) = O(2\(^n\) )。

计算模型

  • 可解性

    ​ 现代意义上的电子计算机所对应的计算模型,就是所谓的图灵机

  • 有效可解

    具体来说就是指存在某一算法,能够在多项式时间以内解决这一问题。反之,若某问题的任一 算法都具有不低于指数的复杂度,则不是有效可解的

  • 下界

    在任何一种特定计算模型下,对于任一可有效解决的问题,任何算法的时间复杂度都 不可能低于某一范围,我们称之为该问题在这一计算模型下的复杂度下界,或简称该问题的下界。

递归

当某个方法调用自己时,我们就称之为递归调用(Recursive call )。

线性递归

​ 类方法的每个实例只能递归地调用自己至多一次.

​ 最后一次递归调用被称作递归的“基底”,简称“递归基”。

性质:经过有限的时间后,它必须能够终止。

线性递归式算法都具有如下形式

  • ​ 检测递归基。首先要检测是否到达递归基,也就是最基本、最简单的情况,在这些平凡情 况下无需做进一步递归调用。
  • ​ 递归处理。如果尚未遇到平凡的情况,则执行一次递归调用。通常,递归调用有多种可能, 此时需要经过进一步的检测以判断具体应按何种方式做递归调用。

递归算法的复杂度分析

递归跟踪法

​ 一种直观的、可视的分析方法,就是将递归方法的执行过程表示为图形的形式.方法的每一实例都对应于一个方框,其中注明了该实例调用的参数;若方法实例 M 调用方法实例 N,则在 M 与 N 对 应的方框之间添加一条有向联线,指明调用与被调用的关系。

递推方程法

对递归的模式进行归纳从而导出关于复杂度函数的递推方程,递归方程的解将给出算法的复杂度。

二分递归

将一个大问题分解为两个子问题,然后分别通过递归调用来求解,这种情 况称作二分递归(Binary recursion )。

多分支递归

一个问题可能需要分解为不止两个子问题,此时就要采用多分支递归(Multiple recursion)。

数据结构与算法 java描述 第一章 算法及其复杂度的更多相关文章

  1. “全栈2019”Java多线程第一章:认识多线程

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  2. “全栈2019”Java异常第一章:什么是异常?

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

  3. 数据结构(Java语言描述)-第一章:概述

    第一章 概述 1.0 序言 自己为啥要学数据结构嘞,我觉得主要有以下三个原因: 前段时间在看并发编程时,发现aqs,corrunthashmap等底层都用到了数据结构,主要的有队列,还有链表,学习数据 ...

  4. 数据结构与算法Java描述 队列

    package com.cjm.queue; /** * 数据结构与算法Java实现 队列 * * @author 小明 * */ public class Myqueue { private Nod ...

  5. [读书笔记]算法(Sedgewick著)·第一章(1)

    到家放松放松之后就开始学习算法了,手里拿的是拿的是一本Robert Sedgewick的橙皮书<算法(第四版)>的.这本书与导论那本书的不同之处在于轻数学思想.重实现,也就是说这是一本很不 ...

  6. Upgrading to Java 8——第一章 Lambda表达式

    第一章 Lambda表达式 Lamada 表达式是Java SE 8中最重要的新特性,长期以来被认为是在Java中缺失的特性,它的出现使整个java 语言变得完整.至少到目前,在这节中你将学习到什么是 ...

  7. JAVA 入门第一章(语法基础)

    本人初学java 博客分享记录一下自己的学习历程 java我的初步学习分为六章,有c和c++的基础学起来也简便了很多. 第一章 语法基础 第二章 面向对象 第三章 常用工具类 第四章 文件操纵 第五章 ...

  8. 深入学习重点分析java基础---第一章:深入理解jvm(java虚拟机) 第一节 java内存模型及gc策略

    身为一个java程序员如果只会使用而不知原理称其为初级java程序员,知晓原理而升中级.融会贯通则为高级 作为有一个有技术追求的人,应当利用业余时间及零碎时间了解原理 近期在看深入理解java虚拟机 ...

  9. javascript 数据结构和算法读书笔记 > 第一章 javascript的编程环境和模型

    1.变量的声明和初始化 必须使用关键字 var,后跟变量名,后面还可以跟一个赋值表达式. var name; var age = 5; var str = 'hello'; var flg = fal ...

随机推荐

  1. Windows10上开启WSL2(Windows Subsystem for Linux 2)及Docker Desktop For Windows

    什么是WSL2 WSL2(Windows Subsystem for Linux 2)是适用于Linux的Windows子系统体系结构的一个新版本,它支持适用于Linux的Windows子系统在Win ...

  2. 关于TreeView的实例

    前台代码 (只需要有TreeView控件, 添加ID,其他默认生成) <form id="form1" runat="server"> <di ...

  3. Error in render: "TypeError: Cannot read property '' of undefined"

    描述 在用Vue的时候出现了一个令人窒息的错误 报错显示 "avatar" 未定义,但在postman中测试返回的数据确实有"avatar",可是为什么未找到? ...

  4. MySql:使用Navicat定时备份数据库

    Navicat自带就有备份  还可以直接计划任务,很方便. 1. 新建计划 打开navicat客户端,连上mysql后,双击左边你想要备份的数据库.点击"计划",再点击" ...

  5. XCTF command_execution

    讲道理这题算是我的思路盲区,先试着ping下本地的地址,127.0.0.1 看了大佬的wp时,我突然意识到,这是放在服务器上执行的,而且服务器一般都是linux系统的,所以linux命令是必需的, 思 ...

  6. Vue3 + Cesium + Typescript 集成搭建的快速启动模板(包含示例数据)

    开门见山 项目地址:https://github.com/tanghaojie/vue3-cesium-typescript-start-up-template 好用的话给个star呗,有更新可以第一 ...

  7. 测试基础(四)Jmeter基础使用

    前言 通过测试基础(三) Jmeter安装 - 大风北吹 - 博客园 (cnblogs.com)安装完成Jmeter后,就可以使用Jmeter进行性能测试. 一.线程组 (1).线程组分类 Jmete ...

  8. Selenium 自动化测试中对页面元素的value比较验证 java语言

    源代码: public boolean verifyText(String elementName, String expectedText) {String actualText = getValu ...

  9. C语言:常用数学函数

    #include <stdio.h> #include <math.h> #include <stdlib.h> #include <time.h> # ...

  10. 密码学系列之:Merkle–Damgård结构和长度延展攻击

    密码学系列之:Merkle–Damgård结构和长度延展攻击 简介 Merkle–Damgård结构简称为MD结构,主要用在hash算法中抵御碰撞攻击.这个结构是一些优秀的hash算法,比如MD5,S ...