时间复杂度

交换排序

主宰稳场 提交于 2019-12-28 04:10:25
基本思想:两两比较待排序记录的关键字,发现两个记录的次序相反时即进行交换,直到没有反序的记录为止。 冒泡排序 1.基本思想 将被排序的记录数组R[1...n]垂直排序,每个记录R[i]看做是重量为R[i].key的气泡。根据轻气泡不能再重气泡之下的原则,从下往上的原则,从下往上(也可以从上往下)扫描数组R,一旦扫描到违反此原则的轻气泡,就使其向上“漂浮”。如此反复进行,直到最后任何两个气泡都是轻者在上、重者在下为止。 2.算法分析 【1】时间复杂度为 O(n^2) 【2】辅助空间复杂度S(n) = O(1),是一个就地排序 【3】冒泡排序是稳定的排序方法 快速排序 1.基本思想 设当前待排序的无序区为R[low...high] 【1】分解 在R[low...high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间 R[low...pivotpos-1]和 R[pivotpos+1...high],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot, pivot=R[pivotpos])的关键字pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置(pivotpos)上,它无须参加后续的排序。划分的关键是求出基准记录所在的位置pivotpos

排序算法总结

有些话、适合烂在心里 提交于 2019-12-28 04:04:51
1、冒泡排序 //冒泡排序 void bubbleSort(int A[], int n) { bool flag = false; for (int i = n - 1; i > 0; i--) { //注意i,j的终止条件 for (int j = 0; j < i; j++) { if (A[j]>A[j + 1])swap(A[j], A[j + 1]); flag = true; } if (flag == false)return; } } View Code (上面代码有误,交换和改变flag值应有大括号) 最差时间复杂度 O(n²) 记录是反序的,需要n-1次扫描,每趟扫描进行n-i次比较,每次比较都要移动3次 最优时间复杂度 O(n) 记录是正序的,一趟扫描即可完成,比较n-1次 平均时间复杂度 O(n²) 虽然冒泡排序不一定进行n-1趟,但记录移动次数多,故平均时间性能比直接插入排序差 最差空间复杂度 O(1) 优点:稳定; 缺点:慢,每次只能移动相邻两个数据 2、插入排序 //插入排序 void insertSort(int A[], int n) { for (int i = 1; i < n; i++) { //注意j从i-1开始 for (int j = i - 1; j >= 0;j--) if (A[i] < A[j]) swap(A[i], A[j

堆排序

僤鯓⒐⒋嵵緔 提交于 2019-12-28 04:00:47
http://www.cnblogs.com/skywang12345/p/3602162.html 堆是一种数据结构,其约束(根节点大于左右子节点——大根堆,根节点小于左右子节点——小根堆),一般用完全二叉树表示,用数组直接存储 堆排序包括两部分:1,构造堆,保证堆的性质 2,输出根节点,并调整堆(将根节点与叶子节点调换,堆的性质被打破)使得余下的节点使其仍然构成堆 堆的插入删除 堆的插入:每次插入都是将新数据放在数组最后。可以发现从这个新数据的父结点到根结点必然为一个有序的数列,现在的任务是将这个新数据插入到这个有序数据中——这就类似于 直接插入排序 中将一个数据并入到有序区间中 // 新加入i结点 其父结点为(i - 1) / 2 void MinHeapFixup(int a[], int i) { int j, temp; temp = a[i]; j = (i - 1) / 2; //父结点 while (j >= 0 && i != 0) { if (a[j] <= temp) break; a[i] = a[j]; //把较大的子结点往下移动,替换它的子结点 i = j; j = (i - 1) / 2; } a[i] = temp; } void MinHeapFixup(int a[], int i) { for (int j = (i - 1) / 2; (j

20182307 2019-2020-1 《数据结构与面向对象程序设计》第七周学习总结

烈酒焚心 提交于 2019-12-27 13:49:59
目录 20182307 2019-2020-1 《数据结构与面向对象程序设计》第七周学习总结 教材学习内容总结 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考试错题总结 学习进度条 点评过的同学博客和代码 20182307 2019-2020-1 《数据结构与面向对象程序设计》第七周学习总结 教材学习内容总结 第12章 算法分析 从算法效率角度分析了软件开发的目标,介绍了算法分析的概念,引进了增长函数与时间复杂度的概念。通过比较不同的算法的增长函数与时间复杂度来分析算法的效率。 第14章 栈 引进了栈这个“先进后出”的线性集合的概念,介绍了栈相关的push,pop,peek等操作。与继承、多态的知识相关联引出了泛型的概念,并以计算后缀表达式为例演示了栈的应用。 第15章 队列 引进了队列这个“先进先出”的线性集合的概念,介绍了队列的enqueue,dequeue等操作。介绍了循环数组解决队空队满情况的方法。 学习笔记: 计算机系统中最重要的资源之一是 CPU时间 。完成具体任务的算法效率是决定 程序执行速度 的一个主要因素。 增长函数 显示了与问题大小相关的时间或空间利用率。 算法的阶 由算法增长函数的主项决定。 处理器速度和内存不能弥补算法增长函数的上界。 集合是收集并组织其他对象的对象。主要分为两类:线性和非线性的。 栈是一个线性集合,处理方式是

Java集合遍历性能

随声附和 提交于 2019-12-27 02:16:17
数据在内存中主要有两种存储方式:   1.顺序存储,Random Access(Direct Access)     这种方式,相邻的数据元素存放于相邻的内存地址中,整块内存地址是连续的,可以根据元素的位置直接计算出内存地址,直接进行读取。读取一个特定位置元素的平均时间复杂度为O(1)。正常来说,只有基于数组实现的集合,才有这种特性。Java中以ArrayList为代表。   2.链式存储,Sequential Access:     这种方式,每一个数据元素,在内存中都不要求处于相邻的位置,每个数据元素包含他的下一个元素的内存地址,不可以根据元素的位置直接计算出内存地址,只能按照顺序读取元素。读取一个特定位置元素的平均时间复杂度为O(n)。主要是以链表为代表。Java中以LinkedList为代表。 遍历方式主要有   1.传统的for循环遍历,基于计数器的:     遍历者自己在集合外部维护一个计数器,然后依次读取每一个位置的元素,当读取到一最后一个元素后,停止。主要是需要按元素的位置来读取。这也是最原始的集合遍历方法。 for (int i = 0; i < list.size(); i++) { list.get(i); }   2.迭代器遍历,Iterator:     Iterator本来是OO的一个设计模式,主要目的是屏蔽不同数据集合的特点,统一遍历集合的接口

数据结构与算法 — 链表

偶尔善良 提交于 2019-12-26 21:58:27
链表 (通过“指针”将一组零散的内存块串联起来使用。) 三种常见链表结构: 单链表:链表通过指针将一组零散的内存块串联在一起。其中,我们把内存块称为链表的“结点”。为了将所有的结点串起来,每个链表的结点除了存储数据之外,还需要记录链上的下一个结点的地址。如图所示,我们把这个记录下个结点地址的指针叫做后继指针next 如图所示,你会发现,其中有两个结点比较特殊,他们分别是第一个结点和最后一个结点。我们习惯把第一个结点叫做头结点,把最后一个结点叫做尾结点。其中,头结点用来记录链表的基地址。有了它,我们可以遍历得到整条链表。而尾结点特殊的地方是:指针不是指向下一个结点,而是指向一个空地址NULL,表示这是链表上最后一个结点。与数组一样,链表也支持数据的查找、插入和删除操作。我们知道,进行数组的插入,删除操作时,为了保持内存的连续性,需要做出大量的数据搬移,所以时间复杂度是O(n)。而在链表中插入或者删除一个数据,我们并不需要为了保持内存的连续性而搬移结点,图中可以看出,针对链表的插入和删除操作,我们只需要考虑相邻结点的指针改变,所以对应时间复杂度是O(1)。 但是有利也有弊。链表想要随机访问第K个元素,就没有数组高效了。因为链表中的数据并非连续存储的,所以无法像数组那样,根据首地址和下标,通过寻址公式就能计算出内存地址,而是需要根据指针一个结点一个结点地依次遍历,直到找到对应的结点。所以

ArrayList与LinkList对比

梦想与她 提交于 2019-12-25 23:51:48
本文简要总结一下java中ArrayList与LinkedList的区别,这在面试中也是常常会问到的一个知识点。 先来看一下ArrayList和LinkedList的关系是怎样的: 从继承体系可以看到,ArrayList与LinkedList都是Collection接口下List接口的实现类。可谓是一对双胞胎。 但由于底层数据结构的不同导致ArrayList与LinkedList有本质上的区别。 ArrayList与LinkedList的区别 ArrayList: ArrayList是基于 动态数组 的数据结构。 因为是数组,所以ArrayList在初始化的时候,有 初始大小10 ,插入新元素的时候,会判断是否需要扩容,扩容的步长是 0.5倍原容量 ,扩容方式是利用 数组的复制 ,因此有一定的开销; 另外,ArrayList在进行元素插入的时候,需要 移动插入位置之后的所有元素 ,位置越靠前,需要位移的元素越多,开销越大,相反,插入位置越靠后的话,开销就越小了,如果在最后面进行插入,那就不需要进行位移; LinkedList: 内部使用基于 链表 的数据结构实现存储,LinkedList有一个内部类作为存放元素的单元,里面有三个属性,用来存放元素本身以及前后2个单元的引用,另外LinkedList内部还有一个header属性,用来标识起始位置

LeetCode解题记录(3)——无重复字符的最长串

允我心安 提交于 2019-12-25 15:58:28
LeetCode解题记录——无重复字符的最长子串 题目说明 测试样例 题意理解 解题方案 滑动窗口法 题目说明 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。 测试样例 输入: “abcabcbb” 输出: 3 最长子串: “abc” 输入: “bbbbb” 输出: 1 最长子串: “b” 输入: “pwwkew” 输出: 3 最长子串: “wke” 题意理解 字符串处理题,实际上也是一个数组的问题,这里需要明确一个问题,这里所指的 子串 ,是字符串的一个 连续子序列 ,题目有以下几个要求 这个子串必须无重复元素 这个子串要求长度是最长的 解题方案 根据题目要求,我们很容易想到穷举所有子串判断其中最大值,这样很显然有着非常高的时间复杂度。 这里考虑到一个窗口的概念,这一概念在很多方面都有所应用,比如计算机网络方面使用窗口限制发送,接受数据序号等。 这里我们使用一个可变大小的滑动窗口表示当前不含重复元素子串的长度,有以下两个状态转移条件: 当最右元素加入窗口使得窗口扩大不破坏不重复原则时,将其加入并扩大窗口 当最右元素加入窗口破坏不重复原则,这时必然有一个元素与最右元素重复,那么只需要将窗口大小缩小到之前的重复元素之后即可 根据这两个转移条件,我们就可以完成合适的转移长度,寻找尽可能少的情况,时间复杂度为O(n)。 解决问题的关键在于如何确定重复元素的位置。

求一个数组中第k大的数方法

房东的猫 提交于 2019-12-25 14:08:41
求一个数组中第k大的数,我第一印象是冒泡,因为只要冒泡k趟即可,第一趟冒泡第一大,第二次冒泡第二大,第k次冒泡第k大,时间复杂度为O(kn),n为数组长度。但是我们都知道快速排序是对冒泡的改进,降低冒泡的递归深度,使时间复杂度降低到O(nlgn),为什么不用快排呢?那么快排的时间复杂度又是多少呢? 因为快排每次将数组划分为两组加一个枢纽元素,每一趟划分你只需要将k与枢纽元素的下标进行比较,如果比枢纽元素下标大就从右边的子数组中找,如果比枢纽元素下标小从左边的子数组中找,如果一样则就是枢纽元素,找到,如果需要从左边或者右边的子数组中再查找的话,只需要递归一边查找即可,无需像快排一样两边都需要递归,所以复杂度必然降低。 最差情况如下:假设快排每次都平均划分,但是都不在枢纽元素上找到第k大 第一趟快排没找到,时间复杂度为O(n),第二趟也没找到,时间复杂度为O(n/2),。。。。。,第k趟找到,时间复杂度为O(n/2 k ),所以总的时间复杂度为 O(n(1+1/2+....+1/2 k ))=O(n),明显比冒泡快,虽然递归深度是一样的,但是每一趟时间复杂度降低。 快排求第k大数代码如下: /* Description: Get K large number in a array for example: a={3,1,4,7,5,8,0}, 5 large number is 5

阿里巴巴2014校招笔试题-2013年9月14日

拥有回忆 提交于 2019-12-25 02:26:42
参考: http://flyown34317.blog.163.com/blog/static/19707301620139112402917/ 1 假设把整数关键码 K 散列到有 N 个槽的散列表,以下哪些散列函数是好的 A、h(k) = k/N B 、h(k) =1 ; C、h(k) =k mod N D、h(k) = (K+ Random(N) ) modN, Random(N ) 返回 0-N-1 的整数 , 2 下面的排序算法中.初始数据集的排列顺序对算法的性能无影响的是 A 堆排序 B 冒泡排序 C、插入排序 D、快速排序 3.下面说法错误的是_。 A、ClSC计算机比RISC计算机指令多 B、在指令格式中,采用扩展操作码设计方案的目的是为了保持指令字长度而增加寻址空间. C、增加流水线段数理论上可以提高CPU频率 D、冯.诺依曼机体系结构的主要特征是存储程序的工作方式 4.不属于冯.诺依曼机体系结构必要组成部分的是_。 A、CPU B、Cache C、RAM D、ROM 输入数据和程序的 输入设备 记忆程序和数据的 存储器 完成数据加工处理的 运算器 控制程序执行的 控制器 输出处理结果的 输出设备 5.一个栈的入栈序列为ABCDE则不可能的输出序列为_。 A、DECBA B、DCEBA C、ECDBA D、ABCDE 6