时间复杂度

经典排序算法--java实现

情到浓时终转凉″ 提交于 2019-11-27 14:10:47
经典排序算法--java实现 概述 算法的性能指标 时间复杂度 空间复杂度 稳定性 简单的桶排序 原理分析 代码实现 性能分析 经典的冒泡排序 原理分析 代码实现 性能分析 性能最好的快速排序 原理分析 代码实现 性能分析 换一种思路—插入排序 原理分析 代码实现 性能分析 插入排序的优化版—shell排序 原理分析 代码实现 性能分析 概述 排序算法是计算机算法里的基础概念,也是很多大厂面试的必考内容。不管你是应届毕业的小鲜肉还是浸淫技术多年的老司机,都免不了会和排序打交道。正因为大部分小伙伴平日的学习和工作中直接接触算法的几率并不大,所以时间久了以后难免生疏。正因为忘的差不多了,所以有必要把一些经典排序算法的思想和实现思路再温习一下。所谓温故而知新,总会有新的收获。 本文涉及的主要知识点: 算法的性能指标 简单的桶排序 经典的冒泡排序 性能最好的快速排序 换一种思路—插入排序 插入排序的优化版—shell排序 算法的性能指标 时间复杂度 时间复杂度是一个函数,使用O表示,一般情况下,时间复杂度由高到低的顺序是O(n 2 )>O(nlogn)>O(n)>O(logn)>O(1)。 一般如果一种算法的时间复杂度高于O(n2),那么就需要考虑是否可以寻找更优化的方案,在代码层面,一般是以循环的嵌套层次来辨别算法的时间复杂度。 比如两层循环嵌套,那么每层循环都需要执行n次,一共是n 2

数据结构和算法绪论

巧了我就是萌 提交于 2019-11-27 13:59:29
什么是数据结构? 数据结构是一门研究非数值计算的程序设计问题中的操作对象,以及它们之间的关系和操作等相关问题的学科。 程序设计 = 数据结构 + 算法 数据结构就是关系,就是数据元素相互之间存在的一种或多种特定关系的集合。 数据结构分为逻辑结构和物理结构 逻辑结构:是数据对象中数据元素之间的相互关系,也是我们今后最需要关注和讨论的问题。(集合结构,线性结构,树形结构,图形结构) 物理结构:是指数据的逻辑结构在计算机中的存储形式。(顺序存储,链式存储) 什么是算法? 算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作。 五个基本特征:输入、输出、有穷性、确定性、可行性。 算法设计要求:正确性、可读性、时间效率高和存储量低。 算法时间复杂度 定义:在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。 算法的时间复杂度,也就是算法的时间量度,记作:T(n)=O(f(n))。 它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐近时间复杂度,称为时间复杂度。其中f(n)是问题规模n的某个函数。 三个求和算法的时间复杂度分别为O(1),O(n),O(n^2)。 循环的时间复杂度 = 循环体的复杂度 * 该循环运行的次数 如何分析算法的时间复杂度?

数据结构之时间复杂度

萝らか妹 提交于 2019-11-27 13:28:47
大O表示法:算法的时间复杂度通常用大O符号表述,定义为T[n] = O(f(n))。称函数T(n)以f(n)为界或者称T(n)受限于f(n)。 如果一个问题的规模是n,解这一问题的某一算法所需要的时间为T(n)。T(n)称为这一算法的“时间复杂度”。当输入量n逐渐加大时,时间复杂度的极限情形称为算法的“渐近时间复杂度”。 迭代程序 题目: int i=1; while(i<=n) { i=i*2; } 思路: 假设循环执行了k次 ,那么 \(2^k\) ≤n,则k≤logn,所以时间复杂度为T(n)=O(logn) 递归程序 主方法 分治法主定理: T[n] = aT[n/b] + f(n) ,其中 n为问题规模 , a≥1 and b>1 是常量 ,并且 f(n)是一个渐进正函数,也就是递归以外的计算时间 ,为了使用这个主定理,需要考虑下列三种情况: 如果 f(n)=O( \(n^{log_ba-ε}\) ) (即 f(n)的指数 小于 \({log_ba}\) ),对于某个常量ε>0成立(即 f(n)为 \(n^{log_ba}\) 的低阶无穷大 ),那么 T(n)=O( \(n^{log_ba}\) ) (即 时间复杂度 取决于 高阶无穷大 ) 如果 f(n)=O( \(n^{log_ba}\) ) (即 f(n)的指数 等于 \({log_ba}\) )(即 f(n)为 \

C语言数据结构-算法

自古美人都是妖i 提交于 2019-11-27 10:31:50
目录 1.算法的定义 2.算法的特性 3.算法设计的要求 4.算法效率的度量方法 5.函数的渐进增长 6.算法时间复杂度 7.其他 @(数据结构算法) 1.算法的定义 ==算法==:是解决特定问题求解步骤的描述,在计算机中表现为指令的优先序列,并且每条指令表示一个或多个操作。(算法是描述解决问题的方法。) 2.算法的特性 输入输出 算法具有零个或多个输入。如打印“hello world!”不需要任何输入参数。 即 算法可以没有输出,但一定要有输入 。 有穷性 ==有穷性==:指算法在执行有限的步骤之后,自动结束而不会出现无限循环,并且每一个步骤在可接受的时间内完成 当然,在现实生活中,如果一个算法需要好几年才能完成,那数学意义上是有穷的,但是算法的意义也就不大了。 确定性 ==确定性==:算法的每一步骤都具有确定的含义,不会出现二义性。 算法在一定条件下,只有一条执行路径,相同的输入只能有唯一的输出结果。算法的每个步骤被精确定义而无歧义。 可行性 ==可行性==:算法的每一步都必须是可行的,也就是说,每一步都能够通过执行有限次数完成。 可行性意味着算法可以转换为程序上机运行,并得到正确的结果。 3.算法设计的要求 正确性 ==正确性==:指算法至少应该具有输入、输出和加工处理无歧义性、能正确反映问题的需求、能够得到问题的正确答案。 大体分为以下四个层次: 1.算法程序没有语法错误。

8-栈

↘锁芯ラ 提交于 2019-11-27 07:39:00
特性 :操作受限的线性表,只允许在一端插入和删除数据,后进先出。 数组或链表确实可以替代栈,但是,特定的数据结构是对特定场景的抽象,而且,数组或链表暴露了太多的操作接口,操作上的确灵活自由,但使用时就比较不可控,自然也就更容易出错。 栈主要包括两个操作,入栈和出栈。 用数组实现的栈叫 顺序栈 ; 用链表实现的栈叫 链式栈 ; 时间复杂度O(1) ,个别情况下O(n),如自动扩容时,进行完整的数据拷贝。 空间复杂度O(1) ,入栈和出栈只需要一两个临时变量存储空间。 我们所说的时间复杂度,是除了原来的数据存储空间外,算法运行还需要的额外的存储空间。 动态扩展的栈 只需要底层依赖一个支持动态扩容的数组就可以了。当栈满了之后,我们就申请一个更大的数组,将原来的数据搬移到新数组中。 时间复杂度分析: 栈空间不够时,我们重新申请一个是原来大小两倍的数组; 为了简化分析,假设只有入栈操作没有出栈操作; 定义不涉及内存搬移的入栈操作为 simple-push 操作,时间复杂度O(1) 如果当前栈大小为 K,并且已满,当再有新的数据要入栈时,就需要重新申请 2 倍大小的内存,并且做 K 个数据的搬移操作,然后再入栈。但是,接下来的 K-1 次入栈操作,我们都不需要再重新申请内存和搬移数据,所以这 K-1 次入栈操作都只需要一个 simple-push 操作就可以完成。 这 K 次入栈操作

JavaScript排序算法

一笑奈何 提交于 2019-11-27 07:14:56
1:基本概念 时间复杂度 :算法执行所耗费的时间。 这个复杂度直接和样本的个数有关,复杂度反映了算法的性能,一般来说,复杂度越低,算法所消耗的时间越短。 /* O(N1) */ for (var i = 0; i < data.length; i++) { ... } /* O(N2) */ for (var i = 0; i < data.length; i++) { for (var j = 0; j < data.length; j++) { ... } } 空间复杂度 :运行一个程序所需内存的大小。 空间复杂度和时间复杂度是对立的,比如说,时间复杂度越高,空间复杂度越低;反之则相反。 内排序 :所有排序操作都在内存中完成。 2:常用的排序算法 冒泡排序(Bubble Sort) 基本概念:依次比较相邻的两个数,将小数放在前面,大数放在后面。 时间复杂度:O(N2)。 实现原理 :重复的走访要排序的数列,一次比较两个元素,大的元素放后面,如果它们的顺序错误就把它们交换过来。 代码实现 :有两层循环嵌套,外循环遍历数组的每一项,内循环用于两两元素的比较,每次内循环减1。 function bubbleSort(arr) { var length = arr.length; for (var i = 0; i < length; i++) { for (var j = 0; j

C/C++实现排序算法(持续更新~~~~~~)

我与影子孤独终老i 提交于 2019-11-27 07:12:54
github: https://github.com/xiaozhengwei/Algorithms-And-DataStructure /** * 冒泡排序 * 时间复杂度(平均) : O(n²) * 时间复杂度(最好) : O(n) * 时间复杂度(最坏) : O(n²) * 空间复杂度 : O(1) * 稳定性: : 稳定 * @param arr : 标记数组首地址的指针 * @param length : 数组长度 * @param type : 排序类型 * @param state : 若数组不再发生变化,则表示已经排序成功,停止排序 * 为0从小到大 * 非0从大到小 */ void bubbleSort(int *arr, int length, int type) { if (length < 2) return; int state = 1;//标记状态,若数组没有发生变化,则停止排序 for (int i = 0; i < length - 1; i++){ for (int j = 0; j < length - i - 1; j++){ if (type ? arr[j] < arr[j + 1] : arr[j] > arr[j + 1]) { arr[j] = arr[j] ^ arr[j + 1]; arr[j + 1] = arr[j] ^

最长公共子串

戏子无情 提交于 2019-11-27 05:41:29
最长公共子串 二维dp 一维dp 思路 代码 二维dp 对于两个数组,我们就假设一个叫a,一个叫b吧,我们要求它们的最长公共子串,我们很容易想到 O ( n 2 ) O(n^2) O ( n 2 ) 的dp,我们可以设一个二维数组, d p [ i ] [ j ] dp[i][j] d p [ i ] [ j ] ,表示a数组的前i个和b数组的前j个的最长公共子串。我们假设存在i,j,使得 a i = b j a_i=b_j a i ​ = b j ​ ,那么,dp[i][j]=dp[i-1][j-1]+1,如果 a i ! = b j a_i!=b_j a i ​ ! = b j ​ ,那么dp[i][j]=max(dp[i][j-1],dp[i-1][j]),这样做的时间复杂度原本是 O ( n 2 ) O(n^2) O ( n 2 ) ,但是我们想我们可以先预处理出来a数组中的数字在b数组中哪些位置出现了,我们这样做下来时间复杂度是均摊的,于是时间复杂度就是 O ( n ) O(n) O ( n ) 的,但是空间复杂度还是 O ( n 2 ) O(n^2) O ( n 2 ) ,于是在有些题中,每个数两两不同,而这种这么高的空间复杂度的做法是不能被接受的,所以我们就有了下面一种做法 一维dp 思路 还是原来的数组名,我们换一个思维,我们用一种加密的思想

java常见排序算法--选择排序、冒泡排序、插入排序分析与比较

回眸只為那壹抹淺笑 提交于 2019-11-27 04:56:07
注:本文是从java语言角度对三种排序算法进行分析比较。 一、选择排序 核心思想: 依次拿当前元素和其后面的元素比较大小,满足条件就互换值 public static int[] shunxu(int[] arr){ int len = arr.length; int temp = 0; for (int i = 0; i < len-1; i++) { for (int j = i+1; j < len; j++) { if(arr[i] > arr[j]){ temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } return arr; } 解读: arr[i]是当前元素,范围是[0,arr.length-1) arr[j]是当前元素后面的元素,范围是[i+1,arr.length) 时间复杂度: 最好的情况是所有数字都是有序的,对于n位的数组,时间复杂度为O(n); 最坏的情况是把顺序的排列变成逆序,或者把逆序的数列变成顺序。在这种情况下,每一次比较都需要进行交换运算。对于n位的数组,则有比较次数为 (n-1) + (n-2) + ... + 1 = n * (n - 1) / 2,这就得到了最大的比较次数。所以时间复杂度为o(n(n-1)/2) 二、冒泡排序 核心思想: 依次拿相邻的元素做比较,满足条件就互换值。

数据结构-数组

折月煮酒 提交于 2019-11-27 04:08:39
  一、数组的概念   定义:数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。   从概念中可以知道一下几点: 数组是线性表。     所谓的线性表就是数据排成一排,想一条线一样的结构。每个线性表上的数据最多只有前和后两个方向。当然除了数组,链表、队列、栈等也是线性表结构        连续的内存空间和形同类型的数据。    正因为有了上述两个特点,数组才能够有一个堪称“杀手锏”的特性:随机访问 数组实现下标随机访问   下面通过一个实际的例子来说明:   例如有一个长度为10的int数组,int[] a = new int[10].      计算机给数组a[10]分配了一块连续的内存空间1000~1039,其中,内存块的首地址为base_address = 1000.   计算机会为每个内存单元分配一个地址,计算机通过地址来访问内存中的数据。当计算即需要随机访问数组中的某个元素的时候,它会首先通过下面的寻址公式,计算该元素存存储的内存地址:            a[i]_address = base_address + i * data_type_size    其中data_type_size表示数组中每个元素的大小。例如,数组中存储的int类型的数据,所以,data_type_size就是4字节。 二、数组的操作