左神算法笔记01
时间复杂度
简单定义
简单理解为: 将一个算法的所有操作拆成基本操作(常数时间完成的操作)后,计算出操作次数和操作时间(可视为1)的乘积,即操作次数之和。在考虑最差情况时用O( )来表示时间复杂度,取最高项来表示。如O(N),O(logN)。
冒泡排序的例子
对N个数进行排列,则最差要进行1+2+3+……+N-1次交换操作和1+2+3+……N-1+N次查看操作,累加即为 N 2 2 + N 2 \frac {N^2} 2 + \frac N 2 2N2+2N,故时间复杂度为O( N 2 N^2 N2)
对数器
一种算法的纠错工具
用其它的保证正确的算法做同一道题,可以不在意效率(如穷举)。用随机数生成大量数据,两个算法一起跑,有差别就用出现差别的数据进行人肉排查,当次数足够多且无差异时,可以认为自己写的算法正确。
异或工具
定义
二进制中,两个数相同的位同为1或同为0时,将该位置为1,否则为0。
可用无进位的加法来理解。符号为:^
异或操作满足交换律和结合律,任意数 ^ 0= 本身
交换两个数的方法
public void swap(array[],i,j)//i和j不等,若相等会报错
{
array[i] = array[i] ^ array[j];
array[j] = array[i] ^ array[j];
array[i] = array[i] ^ array[j];
}
简化一下,array[i]为a,array[j]为b
第一行执行后结果:
a = a ^ b
b = b
第二行执行后结果:
a = a ^ b
b = b ^ a ^ b = b ^ b ^ a = a
第三行执行后结果:
a = a ^ b ^ a = a ^ a ^ b = b
b = a
交换完成
有一组数,只有一个数出现奇数次,其它数出现偶数次,找到这个数
int eor = 0;
for(int i : array)//array为数组
eor ^= i;
出现偶数次的数会两两抵消成为0,剩下的数异或0结果为其本身,即为出现次数为奇数的数。
有一组数,有两个不相同的数出现奇数次,其它数出现偶数次,找到这两个数
首先我们要知道怎么找一个二进制数最右边的1的位置
public int getdiff(int N)//N为待找的数
int index;//为N最右边的1的位产生的数
index = N ^ ((~N) + 1);
return index;
/**
*例:
*N : 00101001000
*~N : 11010110111
*~N+1 : 11010111000
*N ^((~N)+1): 00000001000
*/
我们对数组做一遍同样的操作,
int eor = 0;
for(int i : array)//array为数组
eor ^= i;
此时,我们得到了eor = a ^ b
,假设a,b分别为要找的两个数,那么他们异或的结果起码有一位为1,我们找到最右边为1的位
int index = getdiff(eor);
int a,b;
for(int i : array)
{
if(i & index == 0) a ^= i;
else b ^= i;
}
再将数组分为两块,进行异或操作结束就得到结果。
一些其它的位运算符的操作
a = a << 1;//a*2
a = (a << 1) | 1;//a*2+1
mid = left + (right - left) >> 1;//获取左右的中点