1. 评价算法优劣的核心指标
- 时间复杂度(流程决定)
只关注最高阶,忽略低阶项和所有常数项系数
- 额外空间复杂度(流程决定)
作为输入参数和输出结果的空间不算额外空间,除此之外还需开辟空间支持算法流程的这部分空间叫额外空间
- 常数项时间(实现细节决定)
位运算 快于 ± 快于*/ ,需要申请大空间直接跑看结果 ,放弃理论分析
2. 常见的常数时间的操作:
- 常见的算数运算(±*/%)
- 位运算(>>,<<<,|,&,^)
- 赋值、比较、自增、自减
- 数组寻址
执行时间固定的操作都是常数操作,反之不是
3.常见算法、编程技巧和题目
O(n^2):
插入排序
选择排序
冒泡排序
二分法 【O(log2(N))】:
mid = L + ((R-L) >> 1) 此写法可防止溢出
N * 2 + 1 可写为 (N >> 1) | 1
二分法题:
1. 在一个有序数组中,查找某值是否存在
2. 在一个有序数组中,找>=某个数最左侧的位置
3. 在一个有序数组中,找<=某数的最右侧位置
4. 局部最小值问题
异或运算
即:无进位相加
1. 0 ^ N == N
2. N ^ N == 0
3. 满足交换律和结合律:操作数不管运算顺序,异或结果都一样
题目1:如何不用额外变量就能交换两个值?
a = a ^ b
b = a ^ b
a = a ^ b
注意,a和b不能是同一个内存区域的对象(值可以相同),必须保证内存独立
题目2:一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数?
int eor = 0; 用eor异或所有数得到结果
题目3:如何把一个int类型的数,提取出最右侧的1?
N & ((~N) + 1)
题目4:一个数组中有两种数(不等)出现了奇数次,其他数都出现了偶数次,怎么找到并打印这两种数?
假设这两种数分别为a和b
int eor = 0;
用eor异或所有数得到(eor == a ^ b) != 0
所以a^b必有某位为1,假设第8位为1,那么在第8位上a和b一个是0, 一个是1,
就此可将所有数分为两组,a和b分别在两组中,
一组为第八位为1的,另一组为第八位为0的,然后分别异或 a ^ b得到这两个数
实际应用中,可使用题目3中的方法找到eor最右侧的1,用数字与此数(00001000)与运算分出两组数字即可
题目5:求一个数的二进制1的个数?
取最右1,计数,通过异或抹去这个1