给定一个N个元素的数组,冒泡法排序将: 如果元素大小关系不正确,交换这两个数(在本例中为a> b), 比较一对相邻元素(a,b), 重复步骤1和2,直到我们到达数组的末尾(最后一对是第(N-2)和(N-...1)项,因为我们的数组从零开始) 到目前为止,最大的元素将在最后的位置。...外循环正好运行N次迭代。 但内部循环运行变得越来越短: 当 i = 0,(N-1)次迭代(比较和可能交换)时。 当 i = 1,(N-2)次迭代时,......当 i =(N-2)时,1次迭代, 当 i=(N-1),0迭代. 因此,总迭代次数=(N-1)+(N-2)+ ... + 1 + 0 = N *(N-1)/ 2。...冒泡排序的实例分析 以数组 arr = [5, 1, 4, 2, 8] 为例说明,加粗的数字表示每次循环要比较的两个数字: 第一次外循环 ( 5 1 4 2 8 ) → ( 1 5 4 2 8 ), 5
最后比较a[n-2]与a[n-1]的值。这样处理一轮后,a[n-1]的值一定是这组数据中最大的。 再对a[0]~a[n-2]以相同方法处理一轮,则a[n-2]的值一定是a[0]~a[n-2]中最大的。...算法介绍 设要排序的数组是A[0]……A[n-1] 首先任意选取一个数据作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。...一趟快速排序算法 设置两个变量 i、j,排序开始的时候:i=0,j=n-1; 以第一个数组元素作为关键数据,赋值给 pivot,即 pivot =A[0]; 从 j 开始向前搜索,即由后开始向前搜索(j...); 不过,快排的最坏复杂度即退化为冒泡排序时,时间复杂度为O(n^2),比如一种待排序的序列已经为升序序列,那么每轮分割区间长度为1,n-1,不就是退化为了冒泡排序了吗。...在实际操作中,有很多技术可以降低最坏情况发生的概率,快速排序克服了这个问题后,使得自己应用很广泛。
= n ∗ (n − 1)! 这样的思路就是把⼀个较⼤的问题,转换为⼀个与原问题相似,但规模较⼩的问题来求解的。 n!---> n*(n-1)! (n-1)!...---> (n-1)*(n-2)!.... 直到n是1或者0时,不再拆解 再稍微分析⼀下,当 n<=1 的时候,n的阶乘是1,其余n的阶乘都是可以通过上述公式计算。...1234%10就能得到4,然后1234/10得到123,这就相当于去掉了4 然后继续对123%10,就得到了3,再除10去掉3,以此类推 不断的 %10 和 \10 操作,直到1234的每⼀位都得到;...但是这⾥有个问题就是得到的数字顺序是倒着的,我们以这个思路设想一个Print函数 Print(n) 如果n是1234,那表⽰为 Print(1234) //打印1234的每⼀位 其中1234中的4可以通过...(n-1)+Fib(n-2) int Fib(int n) { if(n<=2) return 1; else return Fib(n-1)+Fib(n-2); } int main() {
因为是从第一个数开始和相邻的数进行比较,所有就需要循环n-1次,即比较n-1趟,又因为每一趟都会找到最大的一个数放在后面,所以每一趟的比较都会比上一趟少比较一次,即n-1次、n-2次、n-3次…..1次...(n是需要排序数字的个数) 二、java代码实现的基本思路 利用二重for循环实现,外重循环设为i(每一趟),内重循环设为j(每一趟的每一次比较),假设有n个数字需要排序,设int[] num=new...int[n],则外循环重复n-1次,内循环重复n-1次、n-2次、n-3次…….1次,所以i的值依次为1、2…..n-1,对应的j的值为n-1、n-2、n-3…….1。...,需要循环n-1次,即比较n-1趟 for (int i = 0; i < num.length – 1; i++) { //内重循环,即每一趟的每一次比较,每次比较n-1次、n-2次、n-3次……...=true ; //设置标志 //内重循环,即每一趟的每一次比较,每次比较n-1次、n-2次、n-3次…….1次 for (int j = 0; j < num.length – 1 – i; j++)
冒泡排序 假设数组arr长度为N,冒泡排序的过程为: 在arr[0~N-1]范围上: arr[0]和arr[1],谁大谁来到1位置; arr[1]和arr[2],谁大谁来到2位置 [N-2]和arr[N...外循环正好运行N次迭代。但内部循环运行变得越来越短: 当 i = 0,(N-1)次迭代(比较和可能交换)时。 当 i = 1,(N-2)次迭代时,......当 i =(N-2)时,1次迭代, 当 i=(N-1),0迭代....估算:很明显,如果arr长度为N,每一步常数操作的数量,如等差数列一般,所以,总的常数操作数量 = a*(N²) + b*N + c (a、b、c都是常数) 所以选择排序的时间复杂度为O(N²)。...很明显,在最差情况下,如果arr长度为N,插入排序的每一步常数操作的数量,还是如等差数列一般。
两个子问题构成了最终问题的解,所以当n>=3时,青蛙就有f(n)=f(n-1)+f(n-2)种跳法。...2 == n) return 2; return fib(n-1)+fib(n-2); } 3.1时间复杂度分析 以递归实现斐波那契数,效率是非常低下的,因为对子问题的求解...设f(n)为参数为n时的时间复杂度,很明显:f(n)=f(n-1)+f(n-2)变为f(n)-f(n-1)+f(n-2)=0,仔细一看,这就是数学上的二阶线性常系数齐次差分方程,求该差分方程的解,就是求得...image.png 有了关于差分方程的一些定义和概念,现在应该知道为什么f(n)-f(n-1)+f(n-2)=0叫作二阶线性常系数齐次差分方程了吧。...关于斐波那契数列递归 求解的期间复杂度我们简化其求解过程,按照如下方式求解。 image.png 递归的时间复杂度是: 递归次数*每次递归中执行基本操作的次数。
两个子问题构成了最终问题的解,所以当 n>=3 时,青蛙就有 f(n) = f(n-1) + f(n-2) 种跳法。...return fib(n-1)+fib(n-2); } 5.1 时间复杂度 以递归实现斐波那契数,效率是非常低下的,因为对子问题的求解 fib(n-1) 和 fib(n-2) 两者存在重叠的部分,对重叠的部分重复计算造成了浪费...设 f(n) 为参数为n时的时间复杂度,很明显,f(n) = f(n-1) + f(n-2) 变为 f(n) - f(n-1) - f(n-2) = 0,仔细一看,这就是数学上的二阶线性常系数齐次差分方程...有了关于差分方程的一些定义和概念,现在应该知道为什么 f(n)-f(n-1)-f(n-2)=0 叫作二阶线性常系数齐次差分方程了吧。...关于斐波那契数列递归求解的期间复杂度我们简化其求解过程,按照如下方式求解。 递归的时间复杂度是:递归次数*每次递归中执行基本操作的次数。所以时间复杂度是: O(2^n) 。
N数组中搜索一个数据x 最好情况:1次找到 最坏情况:N次找到 平均情况:N/2次找到 在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N) 常见复杂度 常数阶O(...Σ(n-1)+(n-2)+...+1 = n(n-1)/2 = O(n^ 2) ,外层循环n次,内层循环每个都为O(n), 所以整体时间复杂度是外层循环次数乘内层循环时间复杂度,即O(n)×O(n)=O..."沉底",即升序排列, 数组长度为n的排序,需要进行n-1轮比较才能完成排序,每一轮循环需要进行n-1次元素比较,最坏情况下每次比较都需要交换元素,所以总共需要进行(n-1)+(n-2)+...+1 =...2^N) 原因: 斐波那契数列的递归定义是:Fib(N) = Fib(N-1) + Fib(N-2),每次调用Fib函数,它会递归调用自己两次。...二叉树的高度就是输入N,每一层节点数都是2的N次方,根据主定理,当问题可以递归分解成固定数目的子问题时,时间复杂度就是子问题数的对数,即O(c^ N )。
我们可以总结下,N个数字要排序完成,总共进行N-1趟排序,第i趟的排序次数为(N-i)次,所以可以用双重循环语句,外层控制循环多少趟,内层控制每一趟的循环次数。...时间复杂度分析 对包含n个数据的数组进行冒泡排序,最坏情况下,需要进行n*(n-1)/2次交换。最好情况下,无需进行交换。取中间值n*(n-1)/4,表示初始有序的的平均情况。...也就是平均情况下需要n*(n-1)/4次交换操作,比较操作肯定要比交换操作多,而这个复杂度的上限是O(n²)。 所以可粗略地认为冒泡排序平均情况下时间复杂度是O(n²)。...,需要比较N-1次; 第二次排序,需要比较N-2次; .........第N-1次排序,需要比较1次; 比较次数=(N-1)+(N-2)+...+1=((1+ N-1)*(N-1))/2=N²/2 + N/2 所以时间复杂度为:O(N²) 三、区别 一、相同点 1.都有两层循环
) 1)有n个数(存放在数组a(n)中),第一趟将每相邻两个数比较,小的调到前头,经n-1次两两相邻比较后,最大的数已“沉底”,放在最后一个位置,小数上升“浮起”; 2)第二趟对余下的n-1个数(最大的数已...“沉底”)按上法比较,经n-2次两两相邻比较后得次大的数; 3)依次类推,n个数共进行n-1趟比较,在第j趟中要进行n-j次两两比较。...,每进行一次测量 ,把测量结果放于队尾 ,而扔掉原来队首的一个数据 ,这样在队列中始终就有 N 个 “最新” 的数据。...当计算平均值时 ,只要把队列中的 N 个数据进行算数平均 ,就可得到新的算数平均值。这样每进行一次测量 ,就可得到一个新的算术平均值。...余数 M[1] = M - b[n-1]*pow(2, 2*n-2) (2) N的次高位b[n-2]可以采用试探法来确定。
A.n/2 B.n C.1 D.n-2 分析:按照上图介绍,把第n-1个元素移动到n,把第n-2个元素移动到n-1,就完成了两次移动。...(n-1)/2 B.n C.2n D.n-i 分析:删除第n-1个位置的元素需要移动0个元素;删除第n-2个位置的元素需要移动1个元素;…;删除第1个位置的元素需要移动n-2个元素;删除第0个位置的元素需要移动...( T ) (3)浏览器记录用户的访问地址以实现“回撤”操作,可以通过“队列”结构来实现。(F ) 分析:这个操作应该是栈的结构来实现的,比如回撤了两次,肯定是先回撤到后访问的地址,是后进先出。...(n阶、n*n)的对称矩阵A的下三角部分(包括主对角线元素)以行序为主序方式存放于一维数组B中,那么,A中任一个下三角元素aij(i≥j≥0)在数组B中的下标位置k(k≥0)为( B )。...分析:第0趟冒泡排序需要进行n-1次元素间的比较,第1趟冒泡排序需要进行n-2次元素间的比较,…,第i次冒泡排序需要进行n-i-1次元素间的比较 (4)稳定的排序算法指( A )。
递归的三大要素 说明:刚开始学习递归可能会使自己一头雾水,看别人写的递归程序总是能够读懂,但是自己实际操作却困难重重,所以,在开始学习之前,不妨掌握递归的精髓,即我们自己写是应当以怎么样的看法去看待递归问题的代码写法...考虑是否重复计算 告诉你吧,如果你使用递归的时候不进行优化,是有非常非常非常多的子问题被重复计算的。 啥是子问题? f(n-1),f(n-2)…就是 f(n) 的子问题了。...例如对于案例2那道题,f(n) = f(n-1) + f(n-2)。递归调用的状态图如下: ? 看到没有,递归计算的时候,重复计算了两次 f(5),五次 f(4)。。。。...补充-递归在内存空间的栈实现 ? 递归的实现可以看作是一次次的压栈操作,我们每调用一次递归体,比如print(n-1),就会一次一次地压栈。...为何无return的递归语句能够实现,主要原因有在栈中递归体的执行顺序是先进后出原则,每次运行完一次递归体(比如n-2)之后,继续执行栈语句相当于进入下一个递归体(n-1)。
在计算F(n)时要先计算F(n-1)和F(n-2),而计算F(n-1)时要先计算F(n-2)和F(n-3),这样就计算了两遍F(n-2)。...由于涉及二维数组的操作,所以对循环遍历的对象要格外注意:遍历的是索引还是下标,尽量避免混淆。...,也就是需要递归调用两次getMostGold(),对于一个规模为n的问题,该算法的时间复杂度为 O(2^n) 。...在走楼梯问题中,F(n-1)和F(n-2)就是F(n)的最优子结构,因为F(n-1)和F(n-2)就是F(n)的最优解。...需要注意的是,这两个数组在交换数据时,并没有使用改变指针方向的方式,是因为这样会导致两个指针指向同一段内存空间,实际是操作同一行的数据而不是两行。
死磕算法系列文章 干货 | 手撕十大经典排序算法 剑指offer | 认识面试 剑指offer | 面试题2:实现Singleton模式 剑指offer | 面试题3:二维数组的查找 剑指offer...递推性质 ,即 f(n)和 f(n-1)…f(1) 之间是有联系的。...当为 1 级台阶:剩 n-1 个台阶,此情况共有 f(n-1)种跳法; 当为 2 级台阶:剩 n-2 个台阶,此情况共有 f(n-2) 种跳法。...f(n) 为以上两种情况之和,即 f(n)=f(n-1)+f(n-2),以上递推性质为斐波那契数列。...n 次,每轮循环内计算操作使用 O(1) 。
添加与搜索单词 - 数据结构设计 一 摘要 在前面算法题目解析:从一道题目看动态规划这篇文章中,描述了动态规划的概念、原理和典型示例,今天用几道典型的动态规划题目来做为练手,达到掌握的目的。70....如果我们从最后一次的选择倒推,f(n)表示到达第n个台阶的可能方法数,那么就可以很容易得到f(n) = f(n-1)+f(n-2)。...当前子问题的解将由上一次子问题的解推导而出。很显然,题目符合这个特征。因此可以使用动态规划的方法。...(1)比较容易,f(n) = f(n-1)+f(n-2)就是我们这个场景的状态转移方程; (2)边界条件,因为状态转移方程需要先知道f(n-1)和f(n-2),所以说递推的计算只能从f(2)开始,并初始化...如果滚动数组不好理解,也可以简单地定义n_1 和 n_2两个变量,每计算一次后,更新n_1=f(i),n_2=f(i-1),下次就可以用这两个值计算f(i+1)了。
第一种跳法:第一次我跳了一个台阶,那么还剩下n-1个台阶还没跳,剩下的n-1个台阶的跳法有f(n-1)种。...第二种跳法:第一次跳了两个台阶,那么还剩下n-2个台阶还没,剩下的n-2个台阶的跳法有f(n-2)种。 所以,小青蛙的全部跳法就是这两种跳法之和了,即 f(n) = f(n-1) + f(n-2)。...这也是我要和你们说的,关于递归结束条件是否够严谨问题,有很多人在使用递归的时候,由于结束条件不够严谨,导致出现死循环。...考虑是否重复计算 告诉你吧,如果你使用递归的时候不进行优化,是有非常非常非常多的子问题被重复计算的。 啥是子问题?f(n-1),f(n-2)….就是 f(n) 的子问题了。...例如对于案例2那道题,f(n) = f(n-1) + f(n-2)。递归调用的状态图如下: ? 看到没有,递归计算的时候,重复计算了两次 f(5),五次 f(4)。。。。
它的基本操作是: 每一次通过n-i次关键字间的比较,从n-i+1个数据中选出关键字最小(大)的数据,并和第i(1≤i≤n)个数据交换 重复n-1次上述操作,直到全部待排序的数据元素排完....算法动图演示如下: 二.简单选择排序的代码实现 算法实现步骤:(以升序为例) 在元素集合arr[i]~arr[n-1]中选择关键码最小(大)的数据元素....在剩余的arr[i+1]~arr[n-1](arr[i]~arr[n-2])集合中,重复上述步骤,直到集合剩余一个元素....: 元素挪动交换次数很少,但是元素比较次数很多,并且无论是数组天生顺序的情况还是天生逆序的情况,元素比较次数都是一样的,都是:T(n)=(n-1)+(n-2)+...+2+1=n(n-1) / 2...而对于交换次数而言,最好的时候,交换次数为0次,最坏的时候,交换次数为n-1次. 基于最终的排序时间是交换次数和比较次数的总和,因此,总的时间复杂度依然是O(n^2).
,只需要遍历一次就可以了,执行N-1次 最坏的情况是顺序是完全相反的 若初始文件是反序的,需要进行n-1趟排序。...每趟排序要进行n-i 次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。...先依次跟0-n异或,并把结果赋值给自己(val^=) 然后再跟数组里的每个元素异或,最后得到的结果就是消失的数字 因为异或顺序不影响结果,相当于 这样0-n跟数组中如果有重复的数字,异或之后结果为零...,数组中消失的数字在0-n中落单,跟val(值为零)异或之后值还是它本身。...基本操作的执行数是T(N) = (N-1)+N O(N) 方法四: 利用等差数列计算 0-n本身就是一种等差数列,根据求和公式减去数组各元素,剩下的值就是消失的数字 O(N) 2.旋转数组OJ链接 输入
递归函数,通过把一个大而复杂问题简化为许多但规模较小的问题,以同一个相似模式来计算,降低了解题的难度;通过调用自身函数,极大地减少了函数代码量的优点而为开发者喜爱。...对数列进行分析,我们发现,从自三项开始,第N项的值就等于其前两项之和,即第N-1和第N-2项的和。...return n; }else{ cache[n-1]=cache[n-1]||fibonacci(n-1);//应用||或运算符“短路”的特性,若在数组中找到其值,则直接使用数组内的值,若没有...,再进行计算,并将值存入数组 cache[n-2]=cache[n-2]||fibonacci(n-2); return cache[n-1]+cache[n-2];//返回数组中的值... } } 由上可以看出,在计算过一次后,数据被存入数组,再次调用时便会优先找到数组内的值而免于大量计算,从而提升效率。
领取专属 10元无门槛券
手把手带您无忧上云