1、学习使用对数器
2、冒泡、选择、插入
3、递归讲解、归并排序的细节讲解
4、小和问题和逆序对问题
对数器的概念和使用
0, 有一个你想要测的方法a,
1, 实现一个绝对正确但是复杂度不好的方法b,
2, 实现一个随机样本产生器
3, 实现比对的方法
4, 把方法a和方法b比对很多次来验证方法a是否正确。
5, 如果有一个样本使得比对出错, 打印样本分析是哪个方法出
错 6,
当样本数量很多时比对测试依然正确, 可以确定方法a已经
正确
1 package basic_class_01; 2 3 import java.util.Arrays; 4 5 public class Code_01_InsertionSort { 6 7 public static void insertionSort(int[] arr) {// 8 if (arr == null || arr.length < 2) {//判断数组是否为空 或者数组元素小于两个数 9 return; 10 } 11 for (int i = 1; i < arr.length; i++) { //从 0~0 插入排序 12 for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) { //核心条件 : j >= 0 && arr[j] > arr[j + 1] 不越界 前面的数大于后边的数 13 swap(arr, j, j + 1); 14 } 15 } 16 } 17 18 public static void swap(int[] arr, int i, int j) {//交换 19 arr[i] = arr[i] ^ arr[j]; 20 arr[j] = arr[i] ^ arr[j]; 21 arr[i] = arr[i] ^ arr[j]; 22 } 23 24 // for test 25 public static void comparator(int[] arr) { // 实现一个绝对正确的方法 复杂度不好的方法 26 Arrays.sort(arr); 27 } 28 29 // for test 30 public static int[] generateRandomArray(int maxSize, int maxValue) { //随机数组发生器 长度 和 大小 31 int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; 32 for (int i = 0; i < arr.length; i++) { 33 arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); 34 } 35 return arr; 36 } 37 38 // for test 39 public static int[] copyArray(int[] arr) { 40 if (arr == null) { 41 return null; 42 } 43 int[] res = new int[arr.length]; 44 for (int i = 0; i < arr.length; i++) { 45 res[i] = arr[i]; 46 } 47 return res; 48 } 49 50 // for test 51 public static boolean isEqual(int[] arr1, int[] arr2) { // 判断两个数组是否相等 52 if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { // 一个空 一个不空 返回flase 53 return false; 54 } 55 if (arr1 == null && arr2 == null) { //都为空返回ture 两个数组一样 56 return true; 57 } 58 if (arr1.length != arr2.length) { //长度不相等 返回flase 59 return false; 60 } 61 for (int i = 0; i < arr1.length; i++) { //数组中的每一个元素 有不相等的 返回flase 62 if (arr1[i] != arr2[i]) { 63 return false; 64 } 65 } 66 return true; //返回true 两个数组相等 67 } 68 69 // for test 70 public static void printArray(int[] arr) { //打印数组 71 if (arr == null) { 72 return; 73 } 74 for (int i = 0; i < arr.length; i++) { 75 System.out.print(arr[i] + " "); 76 } 77 System.out.println(); 78 } 79 80 // for test 81 public static void main(String[] args) { 82 int testTime = 500000; //次数 83 int maxSize = 100; //大小 84 int maxValue = 100; //最大值 85 boolean succeed = true; 86 for (int i = 0; i < testTime; i++) { 87 int[] arr1 = generateRandomArray(maxSize, maxValue); //生成一个随机数组发生器给 arr1 88 int[] arr2 = copyArray(arr1); // 把 arr1 的元素拷贝给arr2 89 insertionSort(arr1); //要测试的方法 90 comparator(arr2); // 绝对正确的方法 91 if (!isEqual(arr1, arr2)) { //判断是否相等 92 succeed = false; 93 break; 94 } 95 } 96 System.out.println(succeed ? "Nice!" : "Fucking fucked!"); 97 98 int[] arr = generateRandomArray(maxSize, maxValue); 99 printArray(arr); 100 insertionSort(arr); 101 printArray(arr); 102 } 103 104 }
1 package com.aixuexi.contact; 2 3 public class BubbleSort { 4 public static void main(String[] args) { 5 int arr[] = new int[] {985,2,6}; 6 //冒泡 O(N*N) 7 for(int end = arr.length-1; end > 0; end--) { 8 for(int i = 0; i < end; i++) { 9 if(arr[i] > arr[i+1]) { 10 int tmp = arr[i]; 11 arr[i] = arr[i+1]; 12 arr[i+1] = tmp; 13 } 14 } 15 } 16 17 //选择 O(N*N) 18 for(int i = 0; i < arr.length -1; ++i) { 19 20 int Indexmin = i; 21 22 for(int j = i + 1; j < arr.length; ++j) { 23 Indexmin = arr[j] < arr[Indexmin] ? j : Indexmin; //返回下表 互换下标 24 } 25 26 //换数 不是换下标 27 int tmp = arr[i]; 28 arr[i] = arr[Indexmin]; 29 arr[Indexmin] = tmp; 30 } 31 32 33 //插入 O(N) 34 for(int i = 1; i < arr.length; i++) { 35 for(int j = i - 1; j >= 0 && arr[j] > arr[j+1]; j--) { 36 arr[i] = arr[j] ^ arr[j+1]; 37 arr[j] = arr[j] ^ arr[j+1]; 38 arr[i] = arr[j] ^ arr[j+1]; 39 } 40 } 41 42 43 System.out.println(); 44 for(int i = 0; i <= arr.length-1; i++) { 45 System.out.printf("%d ",arr[i]); 46 } 47 48 49 } 50 }
2、递归
https://www.cnblogs.com/yaozhenhua/p/11209343.html
一个递归行为的例子
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-master
theorem.html
归并排序的细节讲解
1 package com.aixuexi.contact; 2 3 public class Mergesort { 4 5 public static void mergeSort(int arr[]) { 6 if(arr == null || arr.length <= 2) { 7 return ; 8 } 9 mergeSort(arr,0,arr.length-1); 10 } 11 public static void mergeSort(int arr[],int L,int R) { 12 13 if(L == R) { 14 return ; 15 } 16 int mid = (L + R ) / 2; 17 mergeSort(arr,L,mid); // 排序左边 18 mergeSort(arr,mid+1,R);//排序右边 19 merge(arr,L, mid, R); 20 } 21 public static void merge(int arr[],int L,int mid,int R) { 22 int arr1[] = new int[R - L + 1]; 23 int i = 0; 24 int p1 = L; 25 int p2 = mid + 1; 26 while(p1 <= mid && p2 <= R) { 27 arr1[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++]; 28 } 29 30 while (p1 <= mid) { 31 arr1[i++] = arr[p1++]; 32 } 33 while (p2 <= R) { 34 arr1[i++] = arr[p2++]; 35 } 36 for (i = 0; i < arr1.length; i++) { 37 arr[L + i] = arr1[i]; 38 } 39 40 } 41 42 public static void main(String[] args) { 43 int arr[] = new int[] {1,4,8,3,7,3,43,43,6,8,87,9,4,67}; 44 mergeSort(arr); 45 for(int i = 0; i < arr.length; i++) { 46 System.out.println(arr[i]); 47 } 48 } 49 }
举例:
小和问题
在一个数组中, 每一个数左边比当前数小的数累加起来, 叫做这个数组的小和。 求一个数组
的小和。
例子:
[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
逆序对问题
在一个数组中, 左边的数如果比右边的数大, 则折两个数构成一个逆序对, 请打印所有逆序
对。
package com.aixuexi.contact; /* 2019/7/16 09点25分 * * 总结: 1个问题行数 --28 行 * 注意点 38行 * * return mergeSort(arr, l, mid) + mergeSort(arr, mid + 1, r) + merge(arr, l, mid, r); * res += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0; //算下标 */ 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); // mergeSort(arr, l, mid); // 0 // mergeSort(arr, mid + 1, r); // 0 // int ret = merge(arr, l, mid, r); //ret = 9 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[] = new int[] {1,3,4,2,5}; int res = smallSum(arr); System.out.println(res); // for(int i = 0; i < arr.length; i++) { // System.out.println(arr[i]); // } } }