时间复杂度再学习

时间复杂度再学习

1.认识时间复杂度

常数时间的操作:一个操作如果和数据量没有关系,每次都是 固定时间内完成的操作,叫做常数操作。
时间复杂度为一个算法流程中,常数操作数量的指标。常用O (读作big O)来表示。具体来说,在常数操作数量的表达式中, 只要高阶项,不要低阶项,也不要高阶项的系数,剩下的部分 如果记为f(N),那么时间复杂度为O(f(N))。
评价一个算法流程的好坏,先看时间复杂度的指标,然后再分 析不同数据样本下的实际运行时间,也就是常数项时间

时间复杂度还和数据规模有关,如果有两个算法的,看起优劣,还需要考虑样本量。

选择排序和冒泡排序时间复杂度与数据规模无关,因为数据流程已经确定,插入排序与数据规模有关,最好o(N),全部是有顺序的。

2.对数器的概念和使用

0,有一个你想要测的方法a。

1,实现一个绝对正确但是复杂度不好的方法b。

2,实现一个随机样本产生器 。

3,实现比对的方法 。

4,把方法a和方法b比对很多次来验证方法a是否正确。

5,如果有一个样本使得比对出错,打印样本分析是哪个方法出错。

6,当样本数量很多时比对测试依然正确,可以确定方法a已经 正确。

package basic_class_01;
import java.util.Arrays;
public class Code_00_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,i,i+1);
				}
			}
		}
	}
	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];
	//unsigned int a=60;  //0011 1100
	//	                unsigned int b=13;  //0000 1101
	//	                a=a^b;              //a=a^b=0011 0001
	//	                b=a^b;              //b=a^b=0011 1100  相当于b1=(a^b)^b
	//	                a=a^b;              //a=a^b=0000 1101  相当于a1=(a^b)^((a^b)^b
		    
	}
	//for test
	public static void comparator(int[] arr) {
		Arrays.sort(arr);
	}
	//for test
	public static int[] generateRandomArray(int maxSize,int maxValue) {
		//Math.random()->double[0,1);
		//(int)((size+1)*Math.random())	—>[0,size]整数
		//size=6;size+1=7;
		//Math.random()->[0,1)*7->[0,7)double
		//double->int[0,6]->int
		//生成长度随机的随机数组
	   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;
}
//for test
	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;
	}
	//for test
	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;
}//for test
public static void printArray(int [] arr) {
	if(arr==null) {
		return;
	}
	for(int i=0;i<arr.length;i++) {
		System.out.print(arr[i]+" ");
	}
	System.out.println();
}
//for test
public static void main(String[] args) {
	int testTime=500000;
	int maxSize=10;
	int maxValue=100;
	boolean succeed=true;
	for(int i=0;i<testTime;i++) {
		int [] arr1=generateRandomArray(maxSize,maxValue);
		int[] arr2=copyArray(arr1);
		bubblesort(arr1);
		comparator(arr2);
		if(!isEqual(arr1,arr2)) {
			succeed=false;
			break;
		}
	}
	System.out.println(succeed?"nice":"Fucking");
	int[] arr=generateRandomArray(maxSize,maxValue);
	      printArray(arr);
	      bubblesort(arr);
	      printArray(arr);
}
}
	
	

3.剖析递归行为和递归行为时间复杂度的估算

一个递归行为的例子

递归函数就是系统在帮你压栈,调用子过程的时候在压栈,之后子过程返回值,进行弹栈,还原现场,任何递归行为都可以改为非递归行为。

master公式的使用
T(N) = a*T(N/b) + O(N^d)(划分的子问题的规模每一次是一样的)

例如,T(n)=T(n/5)+T(2/3n)+o(n^2)不能用master公式

T(N)样本量为N的时间复杂度,a表示子过程发生的次数,N/b表示子过程的样本量。

  1. log(b,a) > d -> 复杂度为O(N^log(b,a))

  2. log(b,a) = d -> 复杂度为O(N^d * logN)

  3. log(b,a) < d -> 复杂度为O(N^d)
    补充阅读:www.gocalf.com/blog/algorithm-complexity-and-mastertheorem.html

4.归并排序

T(n)=2T(n/2)+o(n)->o(n*logn)

package basic_class_01;

import java.util.Arrays;

public class Code_05_MergeSort {
public static void mergeSort(int[] arr) {
	if (arr == null || arr.length < 2) {
		return;
	}
	mergeSort(arr, 0, arr.length - 1);
}

public static void mergeSort(int[] arr, int l, int r) {
	if (l == r) {
		return;
	}
	int mid = l + ((r - l) >> 1);
	mergeSort(arr, l, mid);
	mergeSort(arr, mid + 1, r);
	merge(arr, l, mid, r);
}

public static void merge(int[] arr, int l, int m, int r) {
	int[] help = new int[r - l + 1];
	int i = 0;
	int p1 = l;
	int p2 = m + 1;
	while (p1 <= m && p2 <= r) {
		help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
	}
	while (p1 <= m) {
		help[i++] = arr[p1++];
	}
	while (p2 <= r) {
		help[i++] = arr[p2++];
	}
	for (i = 0; i < help.length; i++) {
		arr[l + i] = help[i];
	}
}

// for test
public static void comparator(int[] arr) {
	Arrays.sort(arr);
}

// for test
public static int[] generateRandomArray(int maxSize, int maxValue) {
	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;
}

// for test
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;
}

// for test
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;
}

// for test
public static void printArray(int[] arr) {
	if (arr == null) {
		return;
	}
	for (int i = 0; i < arr.length; i++) {
		System.out.print(arr[i] + " ");
	}
	System.out.println();
}

// for test
public static void main(String[] args) {
	int testTime = 500000;
	int maxSize = 100;
	int maxValue = 100;
	boolean succeed = true;
	for (int i = 0; i < testTime; i++) {
		int[] arr1 = generateRandomArray(maxSize, maxValue);
		int[] arr2 = copyArray(arr1);
		mergeSort(arr1);
		comparator(arr2);
		if (!isEqual(arr1, arr2)) {
			succeed = false;
			printArray(arr1);
			printArray(arr2);
			break;
		}
	}
	System.out.println(succeed ? "Nice!" : "Fucking fucked!");

	int[] arr = generateRandomArray(maxSize, maxValue);
	printArray(arr);
	mergeSort(arr);
	printArray(arr);

}
}

5.小和问题和逆序对问题

小和问题和逆序对问题
小和问题
在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组 的小和。
例子: [1,3,4,2,5] 1左边比1小的数,没有; 3左边比3小的数,1; 4左边比4小的数,1、3; 2左边比2小的数,1; 5左边比5小的数,1、3、4、2; 所以小和为1+1+3+1+1+3+4+2=16

逆序对问题

在一个数组 中,左边的数如果比右边的数大,则折两个数构成一个逆序对,请打印所有逆序 对。

package basic_class_01;

import java.util.Arrays;

public class Code_01_InsertionSort {
public static void insertionSort(int[] arr) {
	if (arr == null || arr.length < 2) {
		return;
	}
	for (int i = 1; i < arr.length; i++) {
		for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
			swap(arr, j, j + 1);
		}
	}
}

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];
}

// for test
public static void comparator(int[] arr) {
	Arrays.sort(arr);
}

// for test
public static int[] generateRandomArray(int maxSize, int maxValue) {
	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;
}

// for test
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;
}

// for test
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;
}

// for test
public static void printArray(int[] arr) {
	if (arr == null) {
		return;
	}
	for (int i = 0; i < arr.length; i++) {
		System.out.print(arr[i] + " ");
	}
	System.out.println();
}

// for test
public static void main(String[] args) {
	int testTime = 500000;
	int maxSize = 100;
	int maxValue = 100;
	boolean succeed = true;
	for (int i = 0; i < testTime; i++) {
		int[] arr1 = generateRandomArray(maxSize, maxValue);
		int[] arr2 = copyArray(arr1);
		insertionSort(arr1);
		comparator(arr2);
		if (!isEqual(arr1, arr2)) {
			succeed = false;
			break;
		}
	}
	System.out.println(succeed ? "Nice!" : "Fucking fucked!");

	int[] arr = generateRandomArray(maxSize, maxValue);
	printArray(arr);
	insertionSort(arr);
	printArray(arr);
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值