1、时间复杂度的定义
常数时间的操作:一个操作如果和数据量没有关系,每次都是固定时间内完成的操作,叫做常数操作。如对比两个数、交换两个数
时间复杂度:常数操作数量的指标,只要高阶项。
评价一个算法流程的好坏,先看时间复杂度的指标,然后再分析不同数据样本下的实际运行时间,也就是常数项时间。
举例:一个有序数组A,另一个无序数组B,请打印B中的所有不在A中的数,A数组长度为N,B数组长度为M。(当因为数据状况使得算法复杂度不同的时候,一律按最差的估计,比如插入排序,如果原数组有序,为O(N),无序,为O(N^2),我们选 O(N^2))
-
对于数组B中的每一个数,都在A中通过遍历的方式找一下;
分析:因为每次都要遍历,所以时间复杂度为O(M*N) -
对于数组B中的每一个数,都在A中通过二分的方式找一下;
分析:二分查找每次都要对半分,一个长度为N的数组可以被对半分logN次,所以总的时间复杂度为:O(M*logN)
注:关于二分查找,请看:二分查找 -
先把数组B排序,然后用类似外排的方式打印所有在A中出现的数;
对于数组B的排序,我们就定义时间复杂度为O(M*logM),外排方式最坏情况是A和B中的元素都被比较了,复杂度为O(M+N), 所以最终的时间复杂度为:O(M*logM)+O(M+N)
2、对数器
2.1 对数器的概念
即用一个笨拙的但是完全正确的算法(如复杂度为O(N^2)的遍历或者直接调用Arrays.sort)和你自己写的算法一起对数组进行排序,来验证你的算法正确性(通常在面试笔试时,需要提前做好模板)
2.2 对数器模板的构建
- comparator:绝对正确的算法,不管是系统自带的排序Arrays.sort还是不考虑复杂度的遍历算法
- generateRandomArray:生成数组,值为随机生成
- copyArray:复制一个数组,地址不同,但是值相同
- isEqual:比较两个数组
- printArray:打印数组
- main:运行和判断
以上,真正需要改动的地方就是comparator绝对正确算法的实现和main函数中对比两个数组的方法
package cn.nupt.test;
import java.util.Arrays;
public class BubbleSort {
// 自己写的排序算法
public static void bubbleSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int e = arr.length - 1; e > 0; e--) {
for (int i = 0; i < e; i++) {
if (arr[i] > arr[i + 1]) {
swap(arr