DivideAndConquer

你所不知道的Java十种经典排序算法

痞子三分冷 提交于 2021-02-07 12:15:02
算法分类 比较排序:在排序的最终结果里,元素之间的次序依赖于他们之间的比较,每个数必须和其他数进行比较,才能确定自己的位置。 优势:适用于一切需要排序的情况。不在乎数据的分布,适用于各种规模的数据 冒泡排序、快速排序、插入排序、希尔排序 、堆排序、选择排序、归并排序。 在冒泡排序之类的排序中,问题规模为n,又因为需要比较n次,所以平均时间复杂度为O(n²)。在归并排序、快速排序之类的排序中,问题规模通过分治法消减为logN次,所以平均时间复杂度为O(nlogn)。 非比较排序:只要确定每个元素之前的已有的元素个数即可,所有一次遍历即可解决。时间复杂度为O(n)。 计数排序、基数排序、桶排序。 非比较排序的时间复杂度低,但是需要占用空间来确定唯一的位置。 递归factorial 方法内部调用方法本身 ⚠️递归的层级太深容易造成栈内存溢出stackOverFlowError 冒泡排序 一次比较相邻的两个元素,如果第一个比第二个大就交换它们两个。 从第一对到结尾的最后一对,重复比较。 重复前面两个步骤(每次都能找到一轮中的最大值)。 算法分析: 最佳情况:T(n) = O(n) 最差情况:T(n) = O(n²) 平均情况:T(n) = O(n²) public static int [ ] bubbleSort ( int [ ] array ) { if ( array .

五种C语言非数值计算的常用经典排序算法

二次信任 提交于 2021-02-01 10:50:10
摘要: 排序是计算机的一种操作方法,其目的是将一组“无序”的记录序列调整为“有序”的记录序列,主要分为内部排序和外部排序。 排序 排序是计算机的一种操作方法,其目的是将一组“无序”的记录序列调整为“有序”的记录序列,主要分为内部排序和外部排序。 (1)冒泡排序(起泡排序) 冒泡排序(Bubble Sort),其基本思路是,对于一组要排序的元素列,依次比较相邻的两个数,将比较小的数放在前面,比较大的数放在后面,如此继续,直到比较到最后的两个数,将小数放在前面,大数放在后面,重复步骤,直至全部排序完成。 优点: 稳定; 缺点: 慢,每次只能移动相邻两个数据。 假设要对含有n个数的序列进行升序排列,冒泡排序算法步骤是: ①从存放序列的数组中的第一个元素开始到最后一个元素,依次对相邻两数进行比较,若前者大后者小,则交换两数的位置; ②第①趟结束后,最大数就存放到数组的最后一个元素里了,然后从第一个元素开始到倒数第二个元素,依次对相邻两数进行比较,若前者大后者小,则交换两数的位置; ③重复步骤①n-1趟,每趟比前一趟少比较一次,即可完成所求。 1、任意读入10个整数,将其用冒泡法按升序排列后输出。 #define n 10 void main() { int a[n],i,j,t; for(i=0;i<n;i++) scanf("%d",&a[i]); for(j=1;j<=n-1;j++)

java基础语法:数据结构和算法

馋奶兔 提交于 2020-11-18 01:52:49
1,数据结构: 数据结构是一种特殊的组织和存储数据的方式,可以使我们可以更高效地对存储的数据执行操作。 数据结构的三要素: 1)逻辑结构: 逻辑结构是指数据元素之间客观存在的关系,和数据在计算机中怎么存储无关,主要用于人们理解和交流以及指导算法的设计。逻辑结构分为四类: 线性结构:数据元素之间存在一对一的关系 树形结构:数据元素之间存在一对多的关系 图形结构:数据元素之间存在多对多的关系 集合结构:数据元素属于同一个集合 2)物理结构(存储结构): 逻辑结构主要用于算法设计,而存储结构用于指导算法编程实现。存储结构有基本的两种结构: 顺序存储:逻辑上相邻的元素存储在物理位置相邻的存储单元中。 链式存储:在数据元素中添加一些地址域或辅助结构,用于存放数据元素之间的关系。 3)数据的运算 数据结构中的操作主要是指数据元素的查找、插入、删除、遍历和排序等等。 2,常用数据结构: 1).数组 在Java中,数组是用来存放同一种数据类型的集合,注意只能存放同一种数据类型。 2).链表 链表是一种非连续、非顺序的结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的,链表由一系列结点组成。 3).堆栈 栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。它体现了后进先出(LIFO)的特点。 4).队列

python实现十大经典算法

戏子无情 提交于 2020-10-28 09:36:26
排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。用一张图概括: 关于时间复杂度: 平方阶 (O(n2)) 排序 各类简单排序:直接插入、直接选择和冒泡排序。 线性对数阶 (O(nlog2n)) 排序 快速排序、堆排序和归并排序。 O(n1+§)) 排序,§ 是介于 0 和 1 之间的常数。 希尔排序。 线性阶 (O(n)) 排序 基数排序,此外还有桶、箱排序。 关于稳定性: 稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序。 不是稳定的排序算法:选择排序、快速排序、希尔排序、堆排序。 名词解释: n:数据规模 k:“桶”的个数 In-place:占用常数内存,不占用额外内存 Out-place:占用额外内存 稳定性:排序后 2 个相等键值的顺序和排序之前它们的顺序相同 冒泡排序 冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

程序员10大算法

落爺英雄遲暮 提交于 2020-10-09 03:01:35
程序员常用的10个算法: 1)2分查找 场景:非递归的二分查找。 (1)之前讲过递归算法. 非递归反而更好理解。 (2)需要先保证数组有序. 2)dac(divide and conquer分治算法) (1)分治算法使用场景: 傅里叶变换 二分搜索 大整数乘法 棋盘覆盖 合并排序 快速排序 线性时间选择 最接近点对问题 循环赛日程表 汉诺塔 (2)如何分、如何治: 看成2部分,AB为1个部分,C为一个部分,那么就是AB移动到b位置,C移动到c位置,AB移动到c位置. 先把最上面的盘A--》B 把最下面的盘A--》C 把B塔的所有盘,从B--》C (3)没有思想,不知道如何拆分是难点. 先有思想,然后把思想转为代码。 3)dynamic(动态规划) 场景: 01背包问题 (1)把大的问题划分为小的问题,从而一步步获取最优解的处理算法 (2)动态规划与分治不同的是: 适用于动态规划求解的问题,经分解得到子问题往往不是独立的。 下一个子阶段的求解是建立在上一个子阶段的解的基础上。 而 分治在2个盘和3个盘的移动是没有什么关系的,是独立的问题。 (3)动态规划是:填表的方式实现的。 思想--》公式--》水到渠成。和数学也没有什么关系。 w[i]: 第i的商品的重量 v[i]: 第i个商品的价值 v[i][j]: 表示在前i个物品中能够装入容量为j v[i][0] = v[0][j] = 0

整理:iOS开发算法资料

℡╲_俬逩灬. 提交于 2020-08-19 22:06:48
关于算法的想法 由于面试可能需要手写算法,网上搜罗了一些资料,整理了下算法的OC的实现代码,虽然平时开发中一般用不到,但是多积累一些技术知识,还是对以后发展大有裨益的 github上搜集的几大算法原理和实现代码,只有JavaScript、Python、Go、Java的实现代码 算法文字理解和OC代码实现 1. 冒泡排序算法(Bubble Sort) 相邻元素进行比较,按照升序或者降序,交换两个相邻元素的位置 是一种“稳定排序算法” 1.1 网上文字理论 是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。 作为最简单的排序算法之一,冒泡排序给我的感觉就像 Abandon 在单词书里出现的感觉一样,每次都在第一页第一位,所以最熟悉。冒泡排序还有一种优化算法,就是立一个 flag,当在一趟序列遍历中元素没有发生交换,则证明该序列已经有序。但这种改进对于提升性能来说并没有什么太大作用。 1.2 算法步骤 比较相邻的元素。如果第一个比第二个大,就交换他们两个。 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。 针对所有的元素重复以上的步骤

【算法系列(一)】:分治

牧云@^-^@ 提交于 2020-08-19 09:12:36
目录 一、基本思想 二、解题思路 三、分治算法一般框架 四、算法应用 169. 多数元素 53. 最大子序和 50. Pow(x, n) 在计算机科学中,分治法是构建基于多项分支递归的一种很重要的算法范式。字面上的解释是「分而治之」,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。 这个技巧是很多高效算法的基础,如排序算法(快速排序、归并排序)、傅立叶变换(快速傅立叶变换)。 另一方面,理解及设计分治法算法的能力需要一定时间去掌握。正如以归纳法去证明一个理论,为了使递归能够推行,很多时候需要用一个较为概括或复杂的问题去取代原有问题。而且并没有一个系统性的方法去适当地概括问题。 分治法这个名称有时亦会用于将问题简化为只有一个细问题的算法,例如用于在已排序的列中查找其中一项的折半搜索算法。这些算法比一般的分治算法更能有效地运行。其中,假如算法使用尾部递归的话,便能转换成简单的循环。但在这广义之下,所有使用递归或循环的算法均被视作“分治算法”。因此,有些作者考虑“分治法”这个名称应只用于每个有最少两个子问题的算法。而只有一个子问题的曾被建议使用减治法这个名称。 分治算法通常以数学归纳法来验证。而它的计算成本则多数以解递归关系式来判定。 一、基本思想 分治算法的主要思想是将原问题 递归地分成 若干个子问题,直到子问题

归并排序

陌路散爱 提交于 2020-08-18 12:59:58
归并排序 1.归并排序介绍:归并排序是比较类中最快的排序算法,其次是快速排序和堆排序,两者排序速度不相上下,但是数据的初始状态对堆排序的影响不大但是却能极大的影响快速排序的排序效率。 2.归并排序的排序思路:归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。主要思路是将一个需要排序的序列通过递归不断的划分成一个小的区间,直至每一个小的区间只有一个元素的时候即可(因为只有一个元素的区间默认是有序的),然后将排序好的子序列进行合并最后合并成一个已经排序好的完整序列。 主要实现代码如下: //合并函数代码: void Merge ( int arr [ ] , int low , int mid , int high ) { //low为第1有序区的第1个元素,i指向第1个元素, mid为第1有序区的最后1个元素 int i = low , j = mid + 1 , k = 0 ; //mid+1为第2有序区第1个元素,j指向第1个元素 int * temp = new int [ high - low + 1 ] ; //temp数组暂存合并的有序序列 while ( i <= mid && j <= high ) { if ( arr [ i ] <= arr [ j ] ) //较小的先存入temp中

53. Maximum Subarray

隐身守侯 提交于 2020-08-18 08:45:08
Given an integer array nums , find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. Example: Input: [-2,1,-3,4,-1,2,1,-5,4], Output: 6 Explanation: [4,-1,2,1] has the largest sum = 6. Follow up: If you have figured out the O( n ) solution, try coding another solution using the divide and conquer approach, which is more subtle. Solution Approach 1: o(n) currSum = max(nums[i], currSum+nums[i]) # The maximum value before the nums[i] maxSum = max(currSum, maxSum) #previous maximum class Solution: def maxSubArray(self, nums: List[int]) -> int:

我在阿里写代码学会的六件事

邮差的信 提交于 2020-08-18 07:30:28
写了多年的代码,始终觉得如何写出干净优雅的代码并不是一件容易的事情。按 10000 小时刻意训练的定理,假设每天 8 小时,一个月 20 天,一年 12 个月,大概也需要 5 年左右的时间成为大师。其实我们每天的工作中真正用于写代码的时间不可能有 8 个小时,并且很多时候是在完成任务,在业务压力很大的时候,可能想要达到的目标是如何尽快的使得功能 work 起来,代码是否干净优雅非常可能没有能放在第一优先级上,而是怎么快怎么来。 在这样的情况下是非常容易欠下技术债的,时间长了,这样的代码基本上无法维护,只能推倒重来,这个成本是非常高的。欠债要还,只是迟早的问题,并且等到要还的时候还要赔上额外的不菲的利息。还债的有可能是自己,也有可能是后来的继任者,但都是团队在还债。所以从团队的角度来看,写好代码是一件非常有必要的事情。如何写出干净优雅的代码是个很困难的课题,我没有找到万能的 solution,更多的是一些 trade off,可以稍微讨论一下。 代码是写给人看的还是写给机器看的? 在大部分的情况下我会认为代码是写给人看的。虽然代码最后的执行者是机器,但是实际上代码更多的时候是给人看的。我们来看看一段代码的生命周期:开发 --> 单元测试 --> Code Review --> 功能测试 --> 性能测试 --> 上线 --> 运维、Bug 修复 --> 测试上线 --> 退休下线