标签:size 次数 运行 空间复杂度 示例 res equal index 关于
内容:
1、时间复杂度
2、简单排序
3、对数器使用
4、递归
注:实现代码为Java
1、时间复杂度
什么是常数时间的复杂度:一个操作如果跟数据量没有关系,每次都是固定时间内完成的操作就叫常数操作
关于时间复杂度:
时间复杂度为一个算法流程中常数操作数量的指标(一般是最差情况下),常用O(读作big O)来表示
具体来说在常数操作数量的表达式中,只要高阶项,不要低阶项,也不要高阶项的系数
然后把剩下的部分记为f(N),那么时间复杂度为O(f(N))
如何平均一个算法好坏:
评价一个算法的好坏,先看时间复杂度的指标,
然后再分析不同数据样本下的实际运行时间,也就是常数项时间
2、简单排序
简单排序是指:冒泡排序、选择排序、插入排序
代码:
1 // 后面都要用到的swap代码: 2 public static void swap(int[] arr, int i, int j){ 3 int temp = arr[i]; 4 arr[i] = arr[j]; 5 arr[j] = temp; 6 } 7 8 // 冒泡排序 -》 每次把最大的数放到最后 9 public static void bubbleSort(int[] arr){ 10 if(arr==null || arr.length<2){ 11 return; 12 } 13 for(int end=arr.length-1; end>=0; end--){ 14 for(int i=0; i<end; i++){ 15 if(arr[i] > arr[i+1]){ 16 swap(arr, i, i+1); 17 } 18 } 19 } 20 } 21 22 // 选择排序 -》 每次选出最小的数放在起始位置 23 public static void selectionSort(int[] arr){ 24 if(arr==null || arr.length<2){ 25 return; 26 } 27 for(int i=0; i<arr.length-1; i++){ 28 int minIndex = i; 29 for(int j=i+1; j<arr.length; j++){ 30 minIndex = arr[j] < arr[minIndex] ? j : minIndex; 31 } 32 swap(arr, i, minIndex); 33 } 34 } 35 36 // 插入排序 -》 将一个数据插入到已经排好序的有序数据中 37 public static void insertionSort(int[] arr) { 38 if (arr == null || arr.length < 2) { 39 return; 40 } 41 for (int i = 1; i < arr.length; i++) { 42 for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) { 43 swap(arr, j, j+1); 44 } 45 46 } 47 }
3、对数器使用
什么是对数器:
1 有一个你想要测试的方法a 2 实现一个绝对正确但是复杂度不好的方法b(好实现能实现的方法) 3 实现一个随机样本产生器 4 实现将两种方法产生的结果对比的方法 5 把方法a和方法b对比很多次来验证方法a是否正确 6 如果有一个样本使得对比出错,打印样本分析是哪个方法出错 7 当样本数量很多时比对测试依然正确,可以确定方法a已经正确 8 9 另外当我们无法保证绝对正确的方法b正确时我们可以减少样本的数量,我们可以在 10 对比验证不等时打印变量,然后看出问题所在
如何使用对数器:
1 以上面的冒泡排序为例: 2 // for test 3 public static void comparator(int[] arr) { 4 // call java built-in sort 5 Arrays.sort(arr); 6 } 7 8 // for test 9 public static int[] generateRandomArray(int maxSize, int maxValue) { 10 // generate a random array 11 // (int) ((maxSize + 1) * Math.random()) -> [0, maxSize] 12 int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; 13 for (int i = 0; i < arr.length; i++) { 14 // value of array element -> [1 - maxValue, maxValue] 15 arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); 16 } 17 return arr; 18 } 19 20 // for test 21 public static int[] copyArray(int[] arr) { 22 // copy a array to another array 23 if (arr == null) { 24 return null; 25 } 26 int[] res = new int[arr.length]; 27 for (int i = 0; i < arr.length; i++) { 28 res[i] = arr[i]; 29 } 30 return res; 31 } 32 33 // for test 34 public static boolean isEqual(int[] arr1, int[] arr2) { 35 // to judge two array is equal 36 if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { 37 return false; 38 } 39 if (arr1 == null && arr2 == null) { 40 return true; 41 } 42 if (arr1.length != arr2.length) { 43 return false; 44 } 45 for (int i = 0; i < arr1.length; i++) { 46 if (arr1[i] != arr2[i]) { 47 // 可以在此打印不一样的值 48 // printArray(arr1); printArray(arr2); 49 return false; 50 } 51 } 52 return true; 53 } 54 55 // for test 56 public static void printArray(int[] arr) { 57 // print all elements of array 58 if (arr == null) { 59 return; 60 } 61 for (int i = 0; i < arr.length; i++) { 62 System.out.print(arr[i] + " "); 63 } 64 System.out.println(); 65 } 66 67 // for test 68 public static void main(String[] args) { 69 // test main function 70 int testTime = 500000; // test times 71 int maxSize = 100; // max size of array 72 int maxValue = 100; // max value of array element 73 boolean succeed = true; 74 for (int i = 0; i < testTime; i++) { 75 // generate a random array and copy the array 76 int[] arr1 = generateRandomArray(maxSize, maxValue); 77 int[] arr2 = copyArray(arr1); 78 bubbleSort(arr1); 79 comparator(arr2); 80 if (!isEqual(arr1, arr2)) { 81 succeed = false; 82 break; 83 } 84 } 85 // if no errors print Nice! else print Funcking fucked! 86 System.out.println(succeed ? "Nice!" : "Fucking fucked!"); 87 88 // to generate a array and bubbleSort it 89 int[] arr = generateRandomArray(maxSize, maxValue); 90 printArray(arr); 91 bubbleSort(arr); 92 printArray(arr); 93 } 94 95 如果输出结果中输出了Fucking fucked!,说明有地方输出不一样, 96 此时我们可以在isEqual函数中打印相关变量来查看
上述函数的解释:
4、递归
递归实质:
递归实质就是系统将当前函数的所有信息压入栈中,然后调用子过程(函数),子过程调用结束后系统从栈中取出栈顶函数相关信息还原现场继续执行函数,故所有递归都可以改成非递归(自己来写压栈)
递归复杂度计算(master公式):
1 通式(master公式): T(N) = aT(N/b) + O(n^d) 2 eg: a=2 b=2 d=0时 T(N) = 2T(N/2) + O(1) 3 计算: 4 log(b, a) > d => 复杂度为: O(N^log(b, a)) 5 log(b, a) = d => 复杂度为: O(N^d * logN) 6 log(b, a) < d => 复杂度为: O(N^d) 7 示例: 8 T(N) = 2T(N/2) + O(1) => O(N) 实际情况: 递归求数组最大值(递归之后只用比较) 9 T(N) = 2T(N/2) + O(N) => O(N*logN) 实际情况: 递归之后还要遍历的 10 T(N) = 2T(N/2) + O(N^2) => O(N^2)
注:其中 a >= 1 and b > 1 是常量,其表示的意义是n表示问题的规模,a表示递归的次数也就是生成的子问题数,b表示每次递归是原来的1/b之一个规模,O(n^d)表示分解和合并所要花费的时间之和(简单说就是递归调用之后的那个常数项时间)
标签:size 次数 运行 空间复杂度 示例 res equal index 关于
原文地址:https://www.cnblogs.com/wyb666/p/10106010.html