最近在看左神的算法课,里面讲到了对数器,在此将其记录下来
对数器的概念
- 有一个你想要测试的方法A
- 实现一个绝对正确,但是时间复杂度不好的方法B
- 实现一个随机样本产生器
- 实现对比的方法
- 把方法A和方法B对比验证很多此来验证方法A是否正确
- 当样本数量很多时比对测试依然正确,可以确定方法a已经正确
对数器的使用
1、写一个需要测试的方法A,以冒泡排序为例
/**
* 去除低阶项,保留高阶项,去除高阶项的系数
* 冒泡排序,时间复杂度=o(N^2)=N*(N-1)*...*1=aN^2+bN+1
*
* @param arr 待排的数组
*/
private static void bubbleSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int end = arr.length - 1; end > 0; end--) {
for (int i = 0; i < end; i++) {
if (arr[i] > arr[i + 1]) {
swap(arr, i, i + 1);
}
}
}
}
/**
* 交换数组中i和j的位置
*
* @param arr 数组
* @param i i
* @param j j
*/
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
2、实现一个绝对正确,但是时间复杂度不好的方法B
/**
* 2.实现一个绝对正确的方法
*
* @param arr
*/
public static void rightMethod(int[] arr) {
Arrays.sort(arr);//JDK自带方法
}
3、实现一个随机样本产生器
/**
* 3.实现一个随机样本产生器
* Math.random():返回double类型的[0,1)之间的数
*
* @param maxSize 数组的最大大小
* @param maxValue 数组数值的最大值
* @return 返回一个最大长度位maxSize,每一个位置在范围[-maxValue,maxValue]的数组
*/
public static int[] generateRandomArray(int maxSize, int maxValue) {
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];//产生一个[0,maxSize]的数组
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
}
4、实现对比的方法
/**
* 数组比较
*
* @param arr1 数组1
* @param arr2 数组2
* @return true/false
*/
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、把以上模板方法整合成一个工具类
public class ArrayUtil {
/**
* 2.实现一个绝对正确的方法
*
* @param arr 随机生成的数组
*/
public static void rightMethod(int[] arr) {
Arrays.sort(arr);
}
/**
* 3.实现一个随机样本产生器
* Math.random():返回double类型的[0,1)之间的数
*
* @param maxSize 数组的最大大小
* @param maxValue 数组数值的最大值
* @return 返回一个最大长度位maxSize,每一个位置在范围[-maxValue,maxValue]的数组
*/
public static int[] generateRandomArray(int maxSize, int maxValue) {
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];//产生一个[0,maxSize]的数组
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
}
/**
* 数组拷贝
*
* @param arr 待拷贝的数组
* @return 新数组
*/
public static int[] arrayCopy(int[] arr) {
int[] newArr = new int[arr.length];
System.arraycopy(arr, 0, newArr, 0, arr.length);
return newArr;
}
/**
* 数组比较
*
* @param arr1 数组1
* @param arr2 数组2
* @return true/false
*/
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;
}
/**
* 打印排序结果
* @param newArray 随机生成的数组
* @param sortArray 排序后的数组
* @param rightArray 正确结果
*/
public static void printCompareResult(int[] newArray,int[] sortArray, int[] rightArray){
System.out.println("生成结果="+Arrays.toString(newArray));
System.out.println("排序结果="+Arrays.toString(sortArray));
System.out.println("正确结果="+Arrays.toString(rightArray));
}
}
2、测试
public static void main(String[] args) {
int maxTime = 50 * 10000;//测试次数
int maxSize = 100;//数组最大大小
int maxValue = 100;//数组子项最大值
boolean isSucceed = true;//是否测试成功
for (int i = 0; i < maxTime; i++) {
int[] array1 = generateRandomArray(maxSize, maxValue);//随机生成的数组
int[] array2 = arrayCopy(array1);//存放正确结果的数组
int[] array3 = arrayCopy(array1);//待排序的数组
bubbleSort(array3);
rightMethod(array2);
if (!isEqual(array3, array2)) {
isSucceed = false;
ArrayUtil.printCompareResult(array1,array3,array2);
break;
}
}
System.out.println(isSucceed ? "Nice!" : "Error!");
}
验证正确:
验证失败: