算法体系-02第二 时间复杂分析(插入/冒泡/选择/二分)

一 时间复杂概念

1.1 算法的复杂度定义

- 只关注最高阶是什么,其他都可以做模糊话处理;因为当我的数据量趋近于很大的时候,算法的优良时间的值只和最高阶有关;估计的时候一定要按照程序最难受的来算;

1.2算法最优解的判断

先保证时间复杂度最低,时间复杂度最低后在保证空间复杂度最低

二 对数器

快速生成测试算法数据的模版

2.1 代码实例



// for test
    public static int[] generateRandomArray(int maxSize, int maxValue) {
        // Math.random()   [0,1)  
        // Math.random() * N  [0,N)
        // (int)(Math.random() * N)  [0, N-1]
        int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
        for (int i = 0; i < arr.length; i++) {
            // [-? , +?]
            arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
        }
        return arr;
    }

二 选择排序及时间复杂度分析

2.1 思路分析

选择排序将已排序部分定义在左端,然后选择未排序部分的最小元素和未排序部分的第一个元素交换。

* 第1趟:在n个数中找到最小(大)数与第一个数交换位置 (时间0- N)

* 第2趟:在剩下n-1个数中找到最小(大)数与第二个数交换位置 时间0- N-1)

* 重复这样的操作...依次与第三个、第四个...数交换位置 

* 第n-1趟,最终可实现数据的升序(降序)排列。时间 n-1 - N-1)

2.2 时间复杂度

0- N  

 0- N-1

.......

n-1 - N-1

等差数列的和

a * n平方+b * n 

按照定义取最高阶既为 o(n)的平方

2.3 代码实例


public class Code01_SelectionSort {

    public static void selectionSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        // 0 ~ N-1  找到最小值,在哪,放到0位置上
        // 1 ~ n-1  找到最小值,在哪,放到1 位置上
        // 2 ~ n-1  找到最小值,在哪,放到2 位置上
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++) { // i ~ N-1 上找最小值的下标 
                minIndex = arr[j] < arr[minIndex] ? j : minIndex;
            }
            swap(arr, i, minIndex);
        }
    }

    public static void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

三 冒泡排序

3.1 思路分析

冒泡排序将已排序部分定义在右端,在遍历未排序部分的过程相邻执行交换,将最大元素交换到最右端。

* 【冒泡排序】:相邻元素两两比较,比较完一趟,最值出现在末尾

* 第1趟:依次比较相邻的两个数,不断交换(小数放前,大数放后)逐个推进,最值最后出现在第n个元素位置

* 第2趟:依次比较相邻的两个数,不断交换(小数放前,大数放后)逐个推进,最值最后出现在第n-1个元素位置

* …… ……

* 第n-1趟:依次比较相邻的两个数,不断交换(小数放前,大数放后)逐个推进,最值最后出现在第2个元素位置

3.2 时间复杂度

计算方法通插入排序

3.3 代码实例


public class Code02_BubbleSort {

    public static void bubbleSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        // 0 ~ N-1
        // 0 ~ N-2
        // 0 ~ N-3
        for (int e = arr.length - 1; e > 0; e--) { // 0 ~ e
            for (int i = 0; i < e; i++) {
                if (arr[i] > arr[i + 1]) {
                    swap(arr, i, i + 1);
                }
            }
        }
    }

    // 交换arr的i和j位置上的值
    public 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];
    }

四 插入排序

4.1 思路分析

插入排序将已排序部分定义在左端,将未排序部分元的第一个元素插入到已排序部分合适的位置。

4.2 复杂度分析

4.3 代码实例


public class Code03_InsertionSort {

    public static void insertionSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        // 不只1个数
        for (int i = 1; i < arr.length; i++) { // 0 ~ i 做到有序
            for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
                swap(arr, j, j + 1);
            }
        }
    }

    // i和j是一个位置的话,会出错
    public 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];
    }

五 三种算法的比较

冒泡排序和插入排序的比较,当数据情况好的情况下,插入排序的时间复杂度好太多;

六 二分法

6.1 查找某个数是否存在数组中


public class Code04_BSExist {

   public static boolean exist(int[] sortedArr, int num) {
      if (sortedArr == null || sortedArr.length == 0) {
         return false;
      }
      int L = 0;
      int R = sortedArr.length - 1;
      int mid = 0;
      // L..R
      while (L < R) { // L..R 至少两个数的时候
         mid = L + ((R - L) >> 1);
         if (sortedArr[mid] == num) {
            return true;
         } else if (sortedArr[mid] > num) {
            R = mid - 1;
         } else {
            L = mid + 1;
         }
      }
      return sortedArr[L] == num;
   }

6.2 局部最小值问题

6.2.1 思路分析


public static int getLessIndex(int[] arr) {
   if (arr == null || arr.length == 0) {
      return -1;
   }
   if (arr.length == 1 || arr[0] < arr[1]) {
      return 0;
   }
   if (arr[arr.length - 1] < arr[arr.length - 2]) {
      return arr.length - 1;
   }
   int left = 1;
   int right = arr.length - 2;
   int mid = 0;
   while (left < right) {
      mid = (left + right) / 2;
      if (arr[mid] > arr[mid - 1]) {
         right = mid - 1;
      } else if (arr[mid] > arr[mid + 1]) {
         left = mid + 1;
      } else {
         return mid;
      }
   }
   return left;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值