算法从小白到大神之时间复杂度&几种排序算法探究
认识时间复杂度
常数时间的操作:一个操作如果和数据量没有关系,每次都是 固定时间内完成的操作,叫做常数操作。
时间复杂度为一个算法流程中,常数操作数量的指标。常用O (读作big O)来表示。具体来说,在常数操作数量的表达式中, 只要高阶项,不要低阶项,也不要高阶项的系数,剩下的部分 如果记为f(N),那么时间复杂度为O(f(N))。
评价一个算法流程的好坏,先看时间复杂度的指标,然后再分 析不同数据样本下的实际运行时间,也就是常数项时间。
例子一
冒泡排序细节的讲解与复杂度分析
时间复杂度O(N^2),额外空间复杂度O(1)
/** * 冒泡排序:时间复杂度O(N^2) * 测试数组: int[] arr={2,4,63,6,9}; * 排序逻辑: * 1、先从数组0-arr.length-1遍历,比较[0-1,1-2,2-3...arr.length-2-arr.length-1]大的放后面, * 最后遍历数组,得到最后的一定是最大的元素 * 2、再从数组0-arr.length-2遍历,比较[0-1,1-2,2-3...arr.length-3-arr.length-2]大的放后面。 * 3、重复以上逻辑 * 排序过程: * 1、[2,4,|63,6,9],[2,4,63,|6,9],[2,4,6,63,|9],[2,4,6,9,63] * 2、[2,4,|6,9,63],[2,4,6,|9,63],[2,4,6,9,|63] * 3、[2,4,|6,9,63],[2,4,6,|9,63] * 4、[2,4,|6,9,63] */ public class BubbleSort { public static void sort(int[] arr){ if (arr==null || arr.length<2){ return; } for (int end = arr.length-1; end>0; end--) { for (int i = 0; i < end; i++) { if (arr[i]>arr[i+1]){ swap(arr,i,i+1); } } } } //交换 private static void swap(int[] arr, int i, int j) { arr[i]=arr[i]^arr[j]; arr[j]=arr[i]^arr[j]; arr[i]=arr[i]^arr[j]; } //for test public static void main(String[] args) { int[] arr={2,4,63,6,9}; sort(arr); System.out.println(Arrays.toString(arr)); } }
例子二
选择排序的细节讲解与复杂度分析
时间复杂度O(N^2),额外空间复杂度O(1)
/** * 选择排序:时间复杂度:O(N^2) * 测试数组:int[]arr={2,3,43,4,5,67,84,3,22,35,64}; * 排序逻辑: * 1、先遍历数组(0-arr.length-1)找最小的那个元素下标:minIndex和i=0位置元素进行交换 * 2、再遍历数组(1-arr.length-1)找最小的那个元素下标:minIndex和index=1位置元素进行交换 * 3、重复步骤。。。。 * 4、最后遍历完了所有元素,最后数组按照从小到大的顺序排列起来了。 * 排序过程: * 1、[2,|3,43,4,5,67,84,3,22,35,64] * 2、[2,3,|43,4,5,67,84,3,22,35,64] * 3、[2,3,3,|43,4,5,67,84,22,35,64] * 4、[2,3,3,4,|43,5,67,84,22,35,64] * 5、[2,3,3,4,5,|43,67,84,22,35,64] * 6、[2,3,3,4,5,22,|67,84,43,35,64] * 7、[2,3,3,4,5,22,35,|84,43,67,64] * 8、[2,3,3,4,5,22,35,43,|84,67,64] * 9、[2,3,3,4,5,22,35,43,64,|67,84] * 10、[2,3,3,4,5,22,35,43,64,67,|84] */ public class SelectionSort { public static void selectionSort(int[]arr){ if (arr==null || arr.length<2){ return; } for (int i = 0; i < arr.length; i++) { int minIndex=i; for (int j = i+1; j < arr.length; j++) { minIndex=arr[j]<arr[minIndex]?j:minIndex; } if (minIndex!=i){ swap(arr,i,minIndex); } } } private static void swap(int[] arr, int i, int j) { arr[i]=arr[i]^arr[j]; arr[j]=arr[i]^arr[j]; arr[i]=arr[i]^arr[j]; } public static void main(String[] args) { int[]arr={2,3,43,4,5,67,84,3,22,35,64}; selectionSort(arr); System.out.println(Arrays.toString(arr)); } }
}
例子三
插入排序的细节讲解与复杂度分析
时间复杂度O(N^2),额外空间复杂度O(1)
/** * 插入排序:时间复杂度O(N^2) * 测试数组: int[] arr={2,4,6,7,4,333}; * 排序逻辑: * 1、先0-1开始,如果前面那个元素大于后面那个元素,就进行交换,交换后前面那个元素是小的 * 2、再从1-2比较两个元素,前一个元素小于后一个元素进行交换,再0-1比较重复步骤2 * 3、再从2-3.。。arr.length-2-array.length-1比较..... * 排序过程: * 1、[2,4,|6,7,4,333] * 2、[2,4,6,|7,4,333] * 3、[2,4,6,7,|4,333] * 4、[2,4,6,4,7,|333] * [2,4,4,6,7,333] * 5、[2,4,4,6,7,333] */ public class InsertSort { public static void insertionSort(int[] arr){ if (arr==null || arr.length<2){ return; } for (int i = 1; i < arr.length; i++) { for (int j = i-1; j >=0&&arr[j]>arr[j+1]; j--) { swap(arr,j,j+1); } } } private static void swap(int[] arr, int i, int j) { arr[i]=arr[i]^arr[j]; arr[j]=arr[i]^arr[j]; arr[i]=arr[i]^arr[j]; } public static void main(String[] args) { int[] arr={2,4,6,7,4,333}; insertionSort(arr); System.out.println(Arrays.toString(arr)); } }
剖析递归行为和递归行为时间复杂度的估算
一个递归行为的例子
master公式的使用T(N) = a*T(N/b) + O(N^d)
1) log(b,a) > d -> 复杂度为O(N^log(b,a))2) log(b,a) = d -> 复杂度为O(N^d * logN)
3) log(b,a) < d -> 复杂度为O(N^d)
补充阅读:www.gocalf.com/blog/algorithm-complexity-and-mastertheorem.html
例子四
归并排序的细节讲解与复杂度分析
时间复杂度O(N*logN),额外空间复杂度O(N)
/** * 二分递归归并排序:时间复杂度:O(N*logN)额外空间复杂度O(N) * 测试数组: int[] arr={1,3,3,6,7,4}; * 排序逻辑: * 1、[1,3,3],[6,7,4] * 2、[1,3],[3] ,[6,7],[4] * 3、[1,3,3] ,[4,6,7] * 4、[1,3,3,4,6,7] */ public class MergeSort { public static void mergeSort(int[] arr){ if (arr==null || arr.length<2){ return; } mergeSort(arr,0,arr.length-1); } private static void mergeSort(int[] arr, int left, int right) { if (left==right){ return; } int mid =left+((right-left)>>1); mergeSort(arr,left,mid); mergeSort(arr,mid+1,right); mergeSort(arr,left,mid,right); } private static void mergeSort(int[] arr, int left, int mid, int right) { int[] help=new int[right-left+1]; int i=0; int p1=left; int p2=mid+1; while (p1<=mid && p2<=right){ help[i++]=arr[p1]<arr[p2]?arr[p1++]:arr[p2++]; } while (p1<=mid){ help[i++]=arr[p1++]; } while (p2<=right){ help[i++]=arr[p2++]; } for (int j = 0; j < help.length; j++) { //二分后每个小的数组的left arr[left+j]=help[j]; } } public static void main(String[] args) { int[] arr={1,3,3,6,7,4}; mergeSort(arr); System.out.println(Arrays.toString(arr)); } }
例子wu
小和问题和逆序对问题
小和问题
在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组 的小和。
例子:[1,3,4,2,5]
1左边比1小的数,没有;
3左边比3小的数,1;
4左边比4小的数,1、3;
2左边比2小的数,1;
5左边比5小的数,1、3、4、2;
所以小和为1+1+3+1+1+3+4+2=16
逆序对问题 在一个数组中,左边的数如果比右边的数大,则折两个数构成一个逆序对,请打印所有逆序 对。
/** * 小和问题 */ public class SmallSum { public static int smallSum(int[] arr) { if (arr == null || arr.length < 2) { return 0; } return mergeSort(arr, 0, arr.length - 1); } public static int mergeSort(int[] arr, int l, int r) { if (l == r) { return 0; } int mid = l + ((r - l) >> 1); return mergeSort(arr, l, mid) + mergeSort(arr, mid + 1, r) + merge(arr, l, mid, r); } public static int merge(int[] arr, int l, int m, int r) { int[] help = new int[r - l + 1]; int i = 0; int p1 = l; int p2 = m + 1; int res = 0; while (p1 <= m && p2 <= r) { res += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0; help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++]; } while (p1 <= m) { help[i++] = arr[p1++]; } while (p2 <= r) { help[i++] = arr[p2++]; } for (i = 0; i < help.length; i++) { arr[l + i] = help[i]; } return res; } public static void main(String[] args) { int [] arr={1,2,3,4,5,6,7,8}; smallSum(arr); System.out.println(Arrays.toString(arr)); } }
本文参考:牛客网
- 常见算法的时间空间复杂度,转载大神的,就当是笔记
- 利用Clion对几种排序算法进行时间复杂度与空间复杂度的分析
- 数据结构几种排序算法的时间和空间复杂度总结
- 常用排序算法的时间和空间复杂度及算法时间复杂度的简单计算
- java面试总结——列举几种排序算法,并说明时间复杂度和空间复杂度
- 几种排序算法时间复杂度对比
- 几种算法的时间和控件复杂度
- 探究O(n^2)和O(nlogn)时间复杂度下各排序算法应用场景(一)
- 常用几种排序算法的时间复杂度和空间复杂度
- 算法学习之一 —— 七种排序算法及其时间复杂度
- 算法 排序算法之时间复杂度和空间复杂度
- 几种常见的排序算法及其时间复杂度——选择排序(三)
- 11. 常见的有哪几种排序算法,试比较其时间复杂度,以及是否稳定,及各自使用的情形
- n个无序整数,已知第i个数在排好序的序列中的位置为j,满足|i-j|<=K,请设计一种排序算法,对该序列进行排序。注:算法时间复杂度为O(nlgn)的得0分,复杂度为O(nk) 的得两分,总分是20分
- 排序算法的C语言实现以及各个算法的时间复杂度和空间复杂度分析(冒泡排序)
- Java数据结构和算法之排序算法介绍与时间复杂度
- 排序算法分类和算法时间复杂度比较
- 【数据结构】排序算法时间效率、空间效率以及算法稳定性总结
- 算法时间复杂度-平方阶
- 各种排序算法比较:时间复杂度,空间复杂度