1.什么是算法?为什么要学习算法?
它是一组具有良好定义的规则,可以有效地解决一些计算方面的问题。如排序,计算最小或是最佳路径距离之类的。
因为算法牛逼,想成为大佬,所有要学。
比如: 判定一个数是否是2的整数次幂?
2 4 8 16 32 64 128 256。。。
a. 取模求余法(最常见的)
b. 由2,联想到二进制;进行逻辑运算 , 找找规律
1--> 01 3--> 011
2--> 10 4--> 100
1&2 == 0 3&4 == 0 (很明显可以) --> 推出 N&(N-1) == 0
1|2 ==11 3|4 ==111 (不行)
7--> 0111 15--> 01111
8--> 1000 16--> 10000
二进制位运算:
按位与运算: 2&6 == 2
按位移运算: 1 < < 2 == 4 相当于:
n<<x相当于 n*2^x
2.时间复杂度和空间复杂度
概念: 时间复杂度是指执行这个算法所需要的计算工作量;而空间复杂度是指执行这个算法所需要的内存空间。
时间复杂度列举:
int a=0; O(1)
int b = a + 1; O(1)
for(int i=0;1<5000;i++){xx} O(5000) => O(1)
常量型时间复杂度 统一为 O(1)。
int n; //未知的
for(int i=0;i<n;i++){xx} O(n)
线性型。
int a=1,n;
while(a < n){
a = a * 2;
=> 2 4 8 16 32...
}
相当于: 2 ^ a =n; => a = log2^n; 应该有人会觉得log的底数是10,而我们这边底数是2,但在算法里面,我们只会用数学的方法把n无限大去比较,所以不管底数是多少,算法的时间复杂度的增长与处理数据多少的增长的关系是一样的。套用规则,这段代码执行次数logn + 1,保留高阶项,去除高阶常数,所以时间复杂度是O(logn)。 -->对数型
for(int i=0;i<n;i++){
while(a < n){
a = a * 2;
}
} => nlog(n)
for(int i=0;i<n;i++){ O(n)
for(int i=0;i<n;i++){O(n)
}
} ==> O(n^2)
for(int i=1; i<=n; i++){
for(int j=i ;i<=n; i++){
}
}
i=1 => 1
i=2 => 2
....
i=n-1 => n-1
i=n => n
即: 1+2+3+....+(n-1)+n 等差数列 => n(n+1)/2 => n^2/2 + n/2 =>(n很大时,常数可以忽略) 为O(n^2)
空间复杂度:(表示占用的内存)
int []a = new int[n]; O(n)
List<String> list = new ArrayList<>();
3.常见的数据结构
1.List
=>Array(ArrayList & Vector单线程安全) 查询快,有下标
链表(LinkedList)插入快,有next结点可直接指向
2.Set
=>HashSet 去重,去重后的顺序和插入顺序不一致
TreeSet 排序,排序后的顺序和插入顺序不一致,底层红黑树
LinkedHashSet 链表实现,记录顺序,保证插入顺序和输出顺序一致
3. Map
=> HashMap 键值对,非线程安全
TreeMap 排序,底层红黑树
ConcurrentHashMap 线程安全
4.Queue(FIFO)
=> 场景:等待、排队、消息队列、优先队列等
PriorityQueue 优先队列
ArrayBlockingQueue 基于数组的阻塞队列
LinkedBlockingQueue 基于链表的阻塞队列,也是无界队列
DelayQueue 延迟队列