算法笔记1(对数器、冒泡、选择、插入、递归、归并、小和问题和逆序对问题 )

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]);
//        }
        
    }

}
原文地址:https://www.cnblogs.com/yaozhenhua/p/11185151.html