异或运算:不进位相加
1. 时间复杂度
所谓常数操作就是跟数据量无关,是一个固定时间的操作。(加减乘除位运算等等)
冒泡排序的时间复杂度为 O ( n 2 ) O(n^2) O(n2)
评价一个算法流程的好坏,先看时间复杂度的指标,然后再分析不同数据样本下的实际运行时间,也就是“常数项时间”。
两个数交换:
a = a 异或 b
b = a 异或 b
a = a 异或 b
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];
}
// i 不能等于 j,不能是同一个内存区域
1.1 例题01,异或运算
链接43:24
在一个数组中,int[],已知只有一种数出现了奇数次,其他所有数都出现了偶数次,
1.怎么找到出现了奇数次的数?
定义一个int数,eor=0,然后将eor和数组中所有数异或。
2.如果已知有两种数出现了奇数次,其他所有数都出现了偶数次,找出这两个出现了奇数次的数?
时间复杂度O(N),空间复杂度O(1)的方法,
进行第一问的操作,得到eor
eor = a ^ b, eor != 0
将eor中的以最后一个出现1的位上(第n位), 分为两种。
eor’ 与数组继续异或,但是只抑或 数组中第n位只出现1或者0的数
package leetcode;
public class First_0228 {
public static void main(String[] args) {
int[] a = {
1,1,1,1,5,5,5,5,9};
int eor = 0;
for (int i : a) {
eor = eor ^ i;
}
System.out.println(eor);
}
}
eor : 1010111100
~eor: 0101000011
~eor+1 : 0101000100
& : 0000000100
// ~取反 &与, 取出最右侧的1来
int rightOne = eor_1 & (~eor_1 + 1);
package leetcode;
public class First_0228 {
public static void main(String[] args) {
int[] list = {
1,1,1,1,5,5,5,5,7,7,7,7,8,9};
int eor_1 = 0;
for (int i : list) {
eor_1 = eor_1 ^ i;
// a!=b eor_1中必有一个位置上为 1
}
// ~取反 &与, 取出最右侧的1来
int rightOne = eor_1 & (~eor_1 + 1);
int onlyOne = 0; // eor'
for (int i : list) {
if((i & rightOne)==0){
onlyOne = onlyOne ^ i;
}
}
eor_1 = onlyOne ^ eor_1;
System.out.println(eor_1);
System.out.println(onlyOne);
}
1.2 插入排序 O( n 2 n^2 n2)
从0-0开始看,到0-1,直到0-n
做到0-0范围上有序,然后0-1范围上有序,一直到0-N范围上有序
从后往前看,若前一个比后一个大则交换,若前面没有数或者相等小于则停止。
public static void insertionSort(int[] arr){
if (arr == null || arr.length<2){
return;
}
for (int i = 0; i < arr.length; i++) {
for (int j = i-1; j >= 0 && arr[j+1]< arr[j] ; 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];
}
1.3 二分法O( l o g 2 N log_2 N log2N)
- 在一个有序数组中,找某个数是否存在?
- 在一个有序数组中,找>=某个数最左侧的位置
- 局部最小值问题
先单独判断0位置是不是局部最小。再看n-1位置是不是局部最小。若没有局部最小,则中间必有局部最小。然后二分到中间m为,判断m-1,m,m+1是否有局部最小。
1.4 对数器
对数器的概念和使用
1,有一个你想要测的方法a
2,实现复杂度不好但是容易实现的方法b
3,实现一个随机样本产生器
4,把方法a和方法b跑相同的随机样本,看看得到的结果是否一样。
5,如果有一个随机样本使得比对结果不一致,打印样本进行人工干预,改对方法a或者
方法b
6,当样本数量很多时比对测试依然正确,可以确定方法a已经正确。
1.5 递归 O ( N ) O(N) O(N)
求数组中的最大值,用递归的方法
master公式为
T ( N ) = 2 ∗ T ( N / 2 ) + O ( 1 ) T(N) = 2* T(N/2) + O(1) T(N)=2∗T(N/2)+O(1)
时间复杂度为 O ( N l o g b a ) = O ( N ) O(N^{log_ba})=O(N) O(Nlogba)=O(N)
master公式
要求每一次子过程规模都是等量的
T ( N ) = a ∗ T ( N / b ) + O ( N d ) T(N) = a* T(N/b) + O(N^d) T(N)=a∗T(N/b)+O(Nd)
母问题共有N个数据
$T(N/b) 每 一 次 子 过 程 规 模 是 等 量 的 , 都 是 每一次子过程规模是等量的,都是 每一次子过程规模是等量的,都是N/b$的规模, 调用了a次.
除去调用之外的时间复杂度是O(N^d)
l o g b