认识复杂度、对数器、二分法
评估算法优劣的核心指标是什么?
时间复杂度(流程决定)、额外空间复杂度(流程决定)、常数项时间(实现细节决定)
时间复杂度
常数时间的的操作(固定时间)
例如1:int a int b (a和b都是固定位数的(由int决定)),a+b 或者减乘除都是一样的不管这个数字本身多复杂 都是固定时间。
例如2:寻址操作
int[一千万] 现在要找int[2百万]和int[8百万],耗费时间是差不多的。知道偏移量即可。
tips:在数组中我们常常认为数组是连续的一片空间,但这里可能会有些许不同就是先分配200万个连续的再指向下一个500万,等等。(这种情况在数组很大的时候可能存在)
位运算、赋值等等。总之执行时间固定的都是常数时间操作,执行时间不固定的都是非常数时间操作。
非常数时间(非固定时间)
linked list 链表的跳转结构。(上一个会指向下一个的地址)
例如,还是1千万长度 但是我要知道200的位置的数据就没法通过偏移量直接知道,因此找到200万和800万位置的时间是不同的。
举个例子
在链表中我用list.get(i)
for (i=0;i < n;i++){
list.get(i)
}
由于每次get(i)方法在链表中找i的时候是每次都重新在0开始找到第i个位置,再加上外面的for循环,因此这里的时间复杂度就是O(N^2)
列流程的时候一定要保证每一步都是固定时间。
如果数据的不同会影响时间复杂度,那就要用最差的情况来表示时间复杂度。
时间复杂度:(最重要)
将问题分解成最小的++常数时间++操作,关注最高阶的结果。例如选择排序、冒泡排序,插入
额外空间复杂度
如果额外开辟的空间只是几个变量 则为O(1) 常数时间,我们看到有几个常数变量,如果这个变量数量不清楚就会变成了O(N)。
例如在哈希表中,如果每个变量都不一样,则找出谁出先次数最多的的额外空间复杂度就是O(N)。
tips:用户传进来的数据 以及他要求返回的数据都不算做额外空间。只是我们在设计流程中所需要额外的变量空间才算额外空间。
常数项时间
时间复杂度指标常常会忽略低阶项和常数项。
拼常数项的时候直接实测 不用理论分析。
因为,某些运算本身就是运算效率不同的例如加减乘除和位运算。位运算更快。
最优解:时间复杂度最好的情况下、空间复杂度优秀、常数项几乎不用管了(面试官一般不管)。
对数器
二分法
经典题目,在一个有序数组中找一个数存不存在。
[12356789] 找3存不存在?
如果遍历找到,时间复杂度O(N)。
用二分法 就是先看中间一个数是比3大还是小 然后只看某一边。
代码中有个注意点:
mid= (L + R)/2
这种方法最好不要写,不安全 有溢出的风险。因为假设计算到右边时R=20亿,L=18亿 两者一加结果就会溢出。
最好改成mid=L + (R-L) >> 1
或者是(L/2 + R/2)也不推荐两次除