感想
这周内容相对基础,更多的是体会老师的思维方式以及解题思路,切记不能眼高手低,要可以练习,共勉
Note
Array
- Java, C++: int a[100];
- Python: list=[]
- JavaScript: let x = [1,2,3Â]
dsec
底层硬件实现,申请数组时计算机在内存中开辟一段连续的地址,每一个地址可直接通过内存管理器(Memory Controller)访问,随机访问任何一个元素时间复杂度都是一样的,增加或删除元素的时候需要让出位置保证内存的连续,需要移动元素 买最好情况 O(1), 最坏情况 O(n), 平均情况 O(n) 的时间复杂度,
advantage:
随机访问速度特别快
disadvantage:
增删操作时间复杂度为 O(n),大量的增删操作很消耗性能
Time Complexity
operation |
Time Complexity |
prepend |
O(1) 如果实现的好可以达到O(1) |
append |
O(1) |
lookup |
O(1) |
insert |
O(n) |
delete |
O(n) |
实现:
JAVA java.util.ArrayList src code
ensureCapacity() 动态扩容
Linked List
desc
弥补数组的缺点,在一些增删操作频繁的情况下,每一个节点 NODE
有包含元素的value
和指向下一个元素的NEXT
, 一般情况下 HEAD
为头指针, NEXT指向null的为TAIL
,我们称之为单链表, 如果定义 指向前一个元所有的 PREV
称之为 双向链表
,如果TAIL
指针指向 HEAD
就称为 循环链表
, 链表插入即 插入位置的 NODE
的NEXT
指向 新NODE
, 新NODE
指向之前的 NEXT
,删除即添加的逆操作, 即 Target Node
的 PREV
的 NEXT
指向 Target Node
,移动元素不会引起链表的群移的操作,所以删除添加元素的时间复杂度为O(1), 但也正是这样的结构访问任意位置需要的时间复杂度为O(n)
Time Complexity
operation |
Time Complexity |
prepend |
O(1) |
append |
O(1) |
lookup |
O(n) |
insert |
O(1) |
delete |
O(1) |
实现
Linked List的标准实现代码
Linked List实例代码
JAVA java>util.LinkedList src code
LRU Cache
Skip List
dsec
跳表是为了优化或补足链表的缺陷设计出来的,链表的缺陷是lookup时间复杂度为O(n),
优化**是升维, 空间换时间
添加头尾指针是最简单的优化,我们可以在头尾指针中间再加上一些指针进一步提高速度, 跳表称为索引,通过增加多级索引,可以为链表提速.
disadvantage
跳表添加和删除元素会导致一些索引不工整的情况(即有些位置很密集,有些位置跨度大),由于索引的持续更新,维护成本较高.空间复杂度为 O(n).
Time Complexity
operation |
Time Complexity |
prepend |
O(1) |
append |
O(1) |
lookup |
O(log2N) |
insert |
O(1) |
delete |
O(1) |
实现
Redis
Stack
FILO
Time Complexity
operation |
Time Complexity |
insertion |
O(1) |
deletion |
O(1) |
search |
O(n) |
Queue
FIFO
Time Complexity
operation |
Time Complexity |
insertion |
O(1) |
deletion |
O(1) |
search |
O(n) |
Deque(Double-Ended Queue)
实际使用中很少直接使用Stack和Queue, 而是直接使用Deque, 实际就是Stack和Queue的结合体,两端都可以进出的Queue
Time Complexity
operation |
Time Complexity |
insertion |
O(1) |
deletion |
O(1) |
search |
O(n) |
Priority Queue
取出顺序不再是FIFO, 按照优先级来取出,底层具体实现的数据结构较为多样和复杂: heap, bst, treap
Time Complexity
operation |
Time Complexity |
insertion |
O(1) |
deletion |
O(1) |
search |
O(logN) |
随堂作业
新api重写代码
Deque<String> deque = new LinkedList<>();
deque.addFirst("a");
deque.addFirst("b");
deque.addFirst("c");
System.out.println(deque);
String str = deque.peekFirst();
System.out.println(str);
System.out.println(deque);
while (deque.size() > 0) {
System.out.println(deque.removeFirst()); System.out.println(deque.pop());
}
System.out.println(deque);
Queue源码分析
add 添加元素到队列中,空间不足抛出异常
offer 元素加入队列
remove 移除头部元素如果队列为null, 返回null
poll 元素移除队列
element 检索head, 如果为null, 抛出异常
peek 检索头部,如果为null,返回null
PriorityQueue源码分析
- 底层使用 可变数组Object[] queue 存储元素
- 不严格先进先出
- 遍历没有顺序保证
源码实现了Queue的基本方法,利用二叉堆的特点(节点的左子树都小于等于其父节点,右子树都大于父节点),对Object[] queue 操作,实现优先特性