算法 就是你设计一些功能 要完成一些流程 设计流程本身就是算法 有时候是做1个处理 有时候是返回1个信息 需要设计流程
有些算法 会使用到一些数据结构 有些数据结构是专门适用于一些算法的 专门为了加速算法或者让算法的流程变得更好 但是 数组以及二叉树结构 它们是专属于某个算法吗? 不是 它就是用来组织数据的结构 是数据结构
算法评估的指标:
第一是 时间复杂度
第二是 额外空间复杂度
第三是 常数项时间
分别介绍一下
常数时间的操作:

比如 你把数组上第100位的数拿出来 以及你把第10000位的数拿出来 时间 不会因为你传进来的 1千 1千亿而有差别 因为内部是直接寻址实现 不是一步一步遍历 去拿到那个值的 所以数组的寻址操作 就是1个固定时间的操作 它和数据量无关 每次时间都固定下来 相反的是链表

注意*和/也算是常数时间的操作哦
非常数时间的操作,比如linkedlist的list.get(i)不是常数时间的操作 它要从前面一直数到i 返回 它是通过指针指的 不是1个连续空间 在内存是分散的
时间复杂度:
比如1个选择排序的过程:
1.下标0到N-1 先把最小的数找到 然后把它和0位置交换一下 0位置的数搞定了
2.然后 1到N-1上再找 这个范围的最小值 然后再和1位置的数交换
3.重复玩这件事

那么这个操作 发生了多少次常数时间操作?
0到N-1可能每个数都要看一下 看的时候 要和之前已经 找到的最小值 做比较
看 就是数组寻址 把数拿出来 和之前找到的最小值比较 如果它更小 我们要记录它的位置
每个位置 0-N-1我们进行 N-1次看+比
然后 过完这些数之后 我们单独做1次交换操作

所以全部加起来


时间复杂度 就是看它增长最大的项 它只关心它的量级 而不是数量级 数量级是以10为底的
排序算法代码
public static void selectSort(int[] arr){
if(arr == null || arr.length < 2){
return;
}
for (int i = 0;i<arr.length;i++){
/**
* 与其去记录最小值 不如记录最小值坐标minIndex
* 因为最小值可能在数组中有相等的 但是每个坐标一定是独一无二的
* 虽然记录值的方法也可以 但是对于对象就失效 如果你要比较的是
* 对象中的某个值 你再记录值对于对象的排序是没有用
* 对象的排序是需要的是地址 即坐标
*/
int minIndex = i;
for(int j=i+1;j<arr.length;j++){
//一行代码 三元表达式 寻找最小坐标
minIndex =(arr[j] < arr[minIndex]) ? j : minIndex;
}
//交换最小值坐标和当前遍的首坐标 降序排序
swap(arr,i,minIndex);
}
}
public static void swap(int[] arr,int i, int j){
/**
* 此swap实现的只是 简单的值传递
* 如果涉及到对象的地址传递 则会出错
*/
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static int[] generateRandomArray(int maxSize,int maxValue){
/**
* 产生一个最大范围内大小的数组(int)((maxSize+1) * Math.random())
* 为什么maxSize和maxValue都要+1
* 因为1.Math.random()产生的数在[0,1)之间
* 2.java的强制类型转化(int)是向下转化的 即1.9->1 1.9999->1
* 所以要+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+1) * Math.random());
}
return arr;
}
public static void main(String[] args) {
int[] arr = generateRandomArray(50,50);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
selectSort(arr);
System.out.println();
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}

有了对数器 你不再依赖 1个题目在线测试的页面 自己就可以改出万无一失的代码 两套思路 两套方法 因为样本产生器是可以控制大小 当它错误时 打印出错误信息 通过断点调试的方法 看1个个的值的变化 人肉的把它调对
实现对数器 需要前面的generatorRandomArray方法
还需要自己写一个copyArray数组方法 来拷贝两个数组 同时跑两个方法 来比较
public static int[] copyArray(int[] arr){
if(arr == null){
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i]
}
return res;
}
还需要一个方法来判断两个数组是否相等的 isEquall
public static boolean isEqual(int[] arr1,int[] arr2){
if ((arr1 == null && arr2 !=null)||(arr1 !=null && arr2 == null)) return false;
if((arr1 == null) && (arr2 ==null))return true;
if(arr1.length!=arr2.length)return false;
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]){
return false;
}
}
return true;
}
因为我们使用系统实现的排序来进行对照 所以要实现1个comparator接口
public static void comparator(int[] arr){
Arrays.sort(arr);
}
public static void printArray(int[] arr){
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]+' ');
}
}
然后对数器 真正实现在main方法中
public static void main(String[] args) {
final int TESTTIME = 500000;
final int MAXSIZE = 100;
final int MAXVALUE = 100;
boolean succeed = true;
for (int i = 0; i < TESTTIME; i++) {
int[] arr1 = generateRandomArray(MAXSIZE,MAXVALUE);
int[] arr2 = copyArray(arr1);
selectSort(arr1);
comparator(arr2);
if (!isEqual(arr1,arr2)){
succeed = false;
printArray(arr1);
printArray(arr2);
break;
}
}
System.out.println(succeed?"Nice!":"Fucking failed");
}
测50w次TESTTIME=5000000 只要错一点 屎都给你测出来

实现1个对数器
包括 1.实现两个效果一样的方法 2.实现1个随机数产生数组 3.对两个方法的结果 进行验证错误 4.排错 这4个步骤 但有些题 是不需要3步骤的 比如找到1个数 根据题目情况而定