常数操作:
概念:固定时间的操作,这些操作不会因为数据量的增多而使得操作的时间变长,例如加,减,乘,除 1+1 和 18912892 + 32837187 的操作时间是相同的。
寻址操作也是常数操作:在数组第0寻找一个值,和从数组第1000000位寻找一个值,可以把指针直接移动到指定位置即可了
时间复杂度:
概念:如果数据量为N ,执行完全部流程常数操作的次数和数据量的关系。
用选择排序来举例:
第一次循环进行 0 ~ n-1 次比较 将得到的最小值和0交换
第二次循环进行 1 ~ n-1 次比较 将得到的最小值和1交换
... ...
第n次循环进行 n ~ n-1 次比较 将得到的最小值和n交换
比较一共进行 n-1 + n-2 + n-3 + ... .... + 0 等差数列
等差数列求和公式:a * n^2 + b * n + c 将公式当中的常数项都去掉,就剩下N^2所以选择排序时间复杂度就为 O(n^2)
额外空间复杂度:
概念:你要实现一个算法流程,在实现算法流程的过程中,你需要开辟一些空间来支持算法路程
注意:输入,输出不算额外空间。
常数项:
一个等差数列求和公式:a * n^2 + b * n + c 常数项是 a,b,c
放弃理论分析,生成随机数据直接测。
算法的最优解:
针对某一个固定的问题,如果时间复杂度,和空间复杂度相同,那么这就是最优解了,可以忽略常数项,常数项只是用来做选择的一个参考。
练习题:
选择排序
// 选择排序核心思路
// 0 - n-1 找最小的 ,找到后交换位置,将最小值放到0位置
// 1 - n-1 找最小的 ,找到后交换位置,将最小值放到1位置
// 2 - n-1 找最小的 ,找到后交换位置,将最小值放到2位置
public static void sort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
int minIndex = i;
for (int j = i; j < arr.length; j++) {
// 寻找最小值
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// 交换位置
swap(arr, i, minIndex);
}
}
冒泡排序
// 核心思路 每次只能得到一个最大值
// 下标位置 0和1 比较
// 下标位置 1和2 比较
public static void sort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
// 如果前面的大于后面的就应该交换
if (arr[j] > arr[j + 1]) {
swap(arr, j, j + 1);
}
}
}
}
插入排序
// 第二次循环得到 0-1 上有顺序的数字 如果小于就交换
// 第二次循环得到 0-2 上有顺序的数字 如果小于就交换
public static void sort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
swap(arr, j, j + 1);
}
}
}
在有序数组当中验证数字是否存在
有序数组中找到>=num最左的位置
局部最小值