算法,画龙点睛之笔也
一.评估算法优劣的核心指标是什么?
1.时间复杂度(流程决定)
2.额外空间复杂度(流程决定)
3.常数项时间(实现细节决定)
常数时间的操作:执行时间固定,与样本量无关
例:
常数的算数运算(+,-,*,/,%)
常见的位运算(>>,>>>,<<,|,&,^)
赋值,比较,自增,自减
数组寻址操作
二.认识时间复杂度
1.时间复杂度
(1)时间复杂度为一个算法流程中,常数操作数量的一个指标,常用O(读作big O)来表示。
(2)先熟悉这个算法流程,然后统计这个算法流程中进行了多少次常数操作,进而写出表达式。
(3)在该表达式中,只要高阶项,不要低阶项,也不要高阶项的系数,剩下的部分如为f(N),那么时间复杂度为O(f(N))
(4)评价一个算法流程的好坏,先看时间复杂度,再分析不同数据样本下的实际运行时间,这个时间就叫“常数项时间”
2.异或运算
性质 | 值 |
---|---|
性质1 | 0^ N= N ;N^ N=0; |
性质2 | a^ b = b^ a;(a^ b)^ c=(a^ b)^c; |
性质3 | 同一组数异或,结果不受先后影响 |
*知识点
不需要其他变量参与的swap()写法:
*注意:这种方式操作的前提要保证a和b在为内存中两个独立的区域
int a=甲;
int b=乙;
a=a^b; //a=甲^乙 b=乙
b=a^b; //a=甲^乙 b=乙^甲^乙=0^甲=甲
a=a^b; //a=甲^乙^甲=0^乙=乙 b=甲
*面试题
给出一个数组,该数组全部为int型数据,
( 时间复杂度为O(N),空间复杂度为O(1) )
(1)数组中有一种数为奇数次,其他数为偶数次
思路:把所有数异或
(2)数组中有两种数为奇数次,其他数为偶数次
思路:
在整型数的32位中,他们必然有1位不一样,而这位就是它们异或
后结果为1的那位,我们通过这一位将整个数组分成两份,使其中一份
异或就可以得到,两个数其中一个数。再异或它俩的异或结果就可以得
到另一个数
public static void q1(int[] arr){
int eor=0;
for(int cur:arr){
eor^=cur;
//eor与数组中全部的数异或,最后得到的是那一种数
}
System.out.println(eor);
}
public static void q2(int[] arr){
int eor=0;
for(int curNUM:arr){
eor^=curNUM;
}
//eor=a^b
//eor!=0
//eor必有一个位置上是1
int rightone=eor&(~eor+1);//提取出一个数最右侧的1 (1*)
int onlyone=0;
for(int cur:arr){
if((cur&rightone)==0){
//把数组中的所有数与rightone相乘等于0的数才把它与onlyone异或
这样就可以数分成两组,而我们要求的两个数必然不在一组,因为
在整型数的32位中,他们必然有1位不一样,而这位就是它们异或
后结果为1的那位,我们通过这一位将整个数组分成两份,使其中一份
异或就可以得到,两个数其中一个数。再异或它俩的异或结果就可以得
到另一个数
onlyone^=cur;
}
}
System.out.println(onlyone+" "+(eor^onlyone));
}
(1*)代码解释
int rightone=eor&(~eor+1);
/*如eor为1010111100
eor: 1010111100
~eor: 0101000011
~eor+1: 0101000100
eor&(~eor+1): 0000000100
*/
3.时间复杂度是按最差情况下的时间来估计
举例:插入排序
解释:当数组的顺序为5,4,3,2,1时,此时插入排序每个数都要进行排序,则需第一个数排0次,第二个数排1次,第三个数排2次,第四个数排3次,第五个数排4次,这是等差数列。则时间复杂度为O(N^2),但当数组顺序为1,2,3,4,5时,此时每个数都不需要进行排序,则时间复杂度为O(N)
*知识点
时间复杂度的还有其他表现形式:
(1)平均时间复杂度的表现形式
(2)最好时间复杂度的表现形式
我们同常用的时间复杂度O()(最差时间复杂度的表现形式)
三. 对数器
解释:
方法a(理论方法) 随机样本产生器 方法b
随机样本产生器产生初始样本分别给方法a和方法b,让两个方法执行该样本
1.随机样本产生器
例子:数组的随机样本产生器
//Math.random->[0,1)所有的小数,等概率返回一个
//Math.random->[0,N)所有小数,等概率返回一个
//(int)(Math.random()*N)->[0,N-1]所有的整数,等概率返回一个
public static int[] RandomArray(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;
}
2.对数器的详细讲解
public static void main(String[] args){
int testTime=50000;//进行50000次对比
int maxSize=100;
int maxValue=100;
boolean s=true;
for(int i=0;i<testTime;i++){
int[] arr1=RandomArray(maxSize,maxValue);
int[] arr2=copyArray(arr1);
insertSort(arr1);
comparator(arr2);
if(!isEqual(arr1,arr2)){
s=false;
break;
}
}
}