注:公式无法显示问题:
- 网络问题
- 安装插件 MathJax Plugin for Github
具体解决方法:
- 网页浏览,参考:https://github.com/wgs666/MathJax_Plugin_for_Github
- 离线浏览
- 01-Linear-Search
01-1-Linear-Search
01-2-Using-Generics
01-3-Using-Custom-Class
01-4-Test-Performance
for (int i = 0; i < data.length; i++)
for (int i = 0; i < data.length; i++)
for (int j = i + 1; j < data.length; j++)
for (int i = 0; i < data.length; i++)
for (int j = 0; j < data.length; j++)
while (n) {
n % x;
n /= x;
}
for (int i = 0; i < = n; i++) {
if (n % i == 0)
}
for (int i = 0; i * i < = n; i++) {
if (n % i == 0)
}
- 02-Selection-Sort
02-1-Selection-Sort
02-2-Using-Generics
02-3-Using-Comparable
02-4-Test-Performance
- 03-Insertion-Sort
03-1-Insertion-Sort
03-2-Insertion-Sort-Optimized
03-3-Insertion-Sort-Features
6 4 2 3 1 5
for (int i = 0; i < arr.length - 1; i++) {//i < arr.length
int minIndex = i;
for (int j = i; j < arr.length; j++) {
if (arr[j].compareTo(arr[minIndex]) < 0)
minIndex = j;
}
swap(arr, i, minIndex);
}
(i = 0,j = 0,1,2,3,4,5):遍历(minIndex = 4)
1 4 2 3 6 5
(i = 1,j = 1,2,3,4,5):遍历(minIndex = 2)
1 2 4 3 6 5
(i = 2,j = 2,3,4,5):遍历(minIndex = 3)
1 2 3 4 6 5
(i = 3,j = 3,4,5):遍历(minIndex = 3)
1 2 3 4 6 5
(i = 4,j = 4,5):遍历(minIndex = 5)
1 2 3 4 5 6
下一步可以省略:
(i = 5,j = 5):遍历(minIndex = 5)
1 2 3 4 5 6
6 4 2 3 1 5
for (int i = 1; i < arr.length; i++) {// i = 0
for (int j = i; j - 1 >= 0; j--) {
if (arr[j].compareTo(arr[j - 1]) < 0)
swap(arr, j - 1, j);
else break;
}
}
for (int i = 1; i < arr.length; i++) {// i = 0
for (int j = i; j - 1 >= 0 && arr[j].compareTo(arr[j - 1]) < 0; j--)
swap(arr, j - 1, j);
}
该步可以省略:
(i = 0):直接跳出
6 4 2 3 1 5
(i = 1,j = 1):遍历比较
4 6 2 3 1 5
(i = 2,j = 2,1):遍历比较
2 4 6 3 1 5
(i = 3,j = 3,2,1):遍历比较
2 3 4 6 1 5
(i = 4,j = 4,3,2,1):遍历比较
1 2 3 4 6 5
(i = 5,j = 5,4,3,2,1):遍历比较
1 2 3 4 5 6
for (int i = 1; i < arr.length; i++) {// i = 0
E t = arr[i];
int j;
for (j = i; j - 1 >= 0; j--) {
if (t.compareTo(arr[j - 1]) < 0)
arr[j] = arr[j - 1];
else
break;
}
arr[j] = t;
}
for (int i = 1; i < arr.length; i++) {// i = 0
E t = arr[i];
int j;
for(j = i; j - 1 >= 0 && t.compareTo(arr[j - 1]) < 0; j --){
arr[j] = arr[j - 1];
}
arr[j] = t;
}
对于有序数组,插入排序的复杂度是
- 线性结构:数组、栈、队列、链表、哈希表
- 树结构:二叉树、二分搜索树、AVL、红黑树、Treap、Splay、堆、Trie、线段树、K-D树、并查集、哈夫曼树
- 图结构:领接矩阵、领接表
- 04-Arrays
04-1-Our-Own-Array
04-2-Add-Element
04-3-Query-and-Update-Element
04-4-Contain-Find-and-Remove
04-5-Generic-Data-Structures
04-6-Dynamic-Array
04-7-Amortized-Time-Complexity
封装属于我们的数组:
- data:数组
- capacity:数组最大容量
- size:数组目前大小
Array()
Array(int capacity)
int getCapacity()
int getSize()
boolean isEmpty()
void add(int index, E e)
void addLast(E e)
void addFirst(E e)
E getElement(int index)
void setElement(int index, E e)
boolean contains(E e)
int find(E e)
E remove(int index)
E removeLast()
E removeFirst()
操作 | 时间复杂度 |
---|---|
add |
|
addLast |
|
addFirst |
|
remove |
|
removeLast |
|
removeFirst |
|
setElement |
|
getElement |
|
contains |
|
find |
总结:
增:
删:
改:已知索引
查:已知索引
均摊复杂度
capacity=8,9次addLast:1 1 1 1 1 1 1 1 8+1 = 17
平均2次基本操作
复杂度震荡
为了避免
/**
* Remove array element
*
* @param index
* @return
*/
public E remove(int index) {
if (index < 0 || index >= size)
throw new IllegalArgumentException("Remove failed. Index is illegal.");
E ret = data[index];
for (int i = index + 1; i < data.length; i++) {
data[i - 1] = data[i];
}
size--;
data[size] = null;
if (size == data.length / 4 && data.length / 2 != 0)
resize(data.length / 2);
return ret;
}
05-Stacks-and-Queues
05-1-Array-Stack
05-2-A-Stack-Problem-in-Leetcode
05-3-Array-Queue
05-4-Loop-Queue
05-5-Queues-Comparison
05-6-Loop-Queue-without-Wasting-One-Space
05-7-Loop-Queue-without-Size-Member
05-8-Deque
封装属于我们的栈:
private Array<E> array;
-
ArrayStack()
-
ArrayStack(int capacity)
-
int getCapacity()
-
int getSize()
-
boolean isEmpty()
-
void push(E e)
-
E pop()
-
E peek()
操作 | 时间复杂度 |
---|---|
getSize() |
|
isEmpty() |
|
push(E e) |
均摊 |
pop() |
均摊 |
peek() |
Leetcode 20. Valid Parentheses
封装属于我们的数组队列:
private Array<E> array;
ArrayQueue(int capacity)
ArrayQueue()
int getCapacity()
int getSize()
boolean isEmpty()
void enqueue(E e)
E dequeue()
E getFront()
操作 | 时间复杂度 |
---|---|
getSize() |
|
isEmpty() |
|
enqueue(E e) |
均摊 |
dequeue() |
|
getFront() |
- 队列为空(front == tail)
- 队列为满((tail + 1)% c == front)
private E[] data;
private int front, tail;
private int size;
LoopQueue(int capacity)
LoopQueue()
int getSize()
boolean isEmpty()
void enqueue(E e)
E dequeue()
E getFront()
队列遍历的两种方式:
for (int i = 0; i < size; i++)
data[(i + front) % data.length]
for (int i = front; i != tail; i = (i + 1) % data.length) {
data[i]
}
操作 | 时间复杂度 |
---|---|
getSize() |
|
isEmpty() |
|
enqueue(E e) |
均摊 |
dequeue() |
均摊 |
getFront() |
private static int opCount = 100000;
封装属于我们的双端队列:
private E[] data;
private int front, tail;
private int size;
Deque(int capacity)
Deque()
int getCapacity()
int getSize()
boolean isEmpty()
void addLast(E e)
void addFirst(E e)
E removeLast()
E removeFirst()
E getFront()
E getLast()
- 06-Linked-List
06-1-Linked-List
06-2-Add-Elements-in-LinkedList
06-3-DummyHead-in-LinkedList
06-4-Query-and-Update-in-LinkedList
06-5-Remove-Element-in-LinkedList
06-6-Implement-Stack-in-LinkedList
06-7-Compare-LinkedList-Stack-and-Array-Stack
06-8-Implement-Queue-in-LinkedList
06-9-Compare-LinkedList-Queue-LoopQueue-and-Array-Queue
- 07-Linked-List-and-Recursion
07-1-Linked-List-Problems-in-Leetcode
07-2-Recursion-Basics
07-3-LinkedList-and-Recursion
07-4-Recursive-Debugging
07-5-Recursive-LinkedList
07-6-Another-Linked-List-Problems-in-Leetcode
封装属于我们的链表:
private class Node {
public E e;
public Node next;
public Node(E e, Node next) {
this.e = e;
this.next = next;
}
public Node(E e) {
this(e, null);
}
public Node() {
this(null, null);
}
@Override
public String toString() {
return e.toString();
}
}
private Node head;// private Node dummyHead;
private int size;
LinkedList()
int getSize()
boolean isEmpty()
void add(int index, E e)
void addFirst(E e)
void addLast(E e)
E get(int index)
E getFirst()
E getLast()
void set(int index, E e)
boolean contains(E e)
E remove(int index)
E removeFirst()
E removeLast()
void removeElement(E e)
操作 | 时间复杂度 |
---|---|
getSize() |
|
isEmpty() |
|
add |
|
addFirst |
|
addLast |
|
get |
|
getFirst |
|
getLast |
|
set |
|
contains |
|
remove |
|
removeFirst |
|
removeLast |
使用链表封装属于我们的栈:
private LinkedList<E> list;
LinkedListStack()
int getSize()
boolean isEmpty()
void push(E e)
E pop()
E peek()
private static int opCount = 100000;
使用链表封装属于我们的队列:
private class Node {
public E e;
public Node next;
public Node(E e, Node next) {
this.e = e;
this.next = next;
}
public Node(E e) {
this(e, null);
}
public Node() {
this(null, null);
}
@Override
public String toString() {
return e.toString();
}
}
private Node head, tail;
private int size;
LinkedListQueue()
int getSize()
boolean isEmpty()
void enqueue(E e)
E dequeue()
E getFront()
private static int opCount = 100000;
203. Remove Linked List Elements
常规解法(分开讨论):
public ListNode removeElements(ListNode head, int val) {
while (head != null && head.val == val)
head = head.next;
if (head == null)
return null;
else {
ListNode prev = head;
while (prev.next != null)
if (prev.next.val == val)
prev.next = prev.next.next;
else
prev = prev.next;
return head;
}
}
虚拟头节点:
public ListNode removeElements(ListNode head, int val) {
ListNode dummyHead = new ListNode(-1);
dummyHead.next = head;
ListNode prev = dummyHead;
while (prev.next != null)
if (prev.next.val == val)
prev.next = prev.next.next;
else
prev = prev.next;
return dummyHead.next;
}
转换为最基本问题
private static int sum(int[] arr, int l) {
if (l == arr.length)
return 0;
return arr[l] + sum(arr, l + 1);
}
举例:arr= [6,10]
-
sum(arr,0)
-
sum(arr,1)
-
sum(arr,2) return 0
-
return arr[1] + sum(arr,2) = 10 + 0 = 10 (sum(arr,1))
-
return arr[0] + sum(arr,0) = 6 + 10 = 16 (sum(arr,0))
链表&递归
public ListNode removeElements(ListNode head, int val) {
if (head == null) return null;// 1
head.next = removeElements(head.next, val); // 2
return head.val == val ? head.next : head;// 3
}
举例:6 -> 7 -> 8 -> null
-
$head:6 \rightarrow7 \rightarrow8 \rightarrow null$ :removeElements(head,6)- 1
- 2
-
$head:7 \rightarrow8 \rightarrow null$ :removeElements(head,6)- 1
- 2
-
$head:8 \rightarrow null$ :removeElements(head,6)- 1
- 2
-
$head:null$ :removeElements(head,6)- 1:return null
- 8 -> null
- 3:return 8 -> null
- 7 -> 8 -> null
- 3:return 8 -> null
- 6 -> 8 -> null
- 3:return 6 -> 8 -> null
递归深度
public ListNode removeElements(ListNode head, int val, int depth) {
String depthString = generateDepthString(depth);
System.out.print(depthString);
System.out.println("Call: remove " + val + " in " + head);
if (head == null) {
System.out.print(depthString);
System.out.println("Return: " + head);
return head;
}
ListNode res = removeElements(head.next, val, depth + 1);
System.out.print(depthString);
System.out.println("After remove " + val + ": " + res);
ListNode ret;
if (head.val == val)
ret = res;
else {
head.next = res;
ret = head;
}
System.out.print(depthString);
System.out.println("Return: " + ret);
return ret;
}
使用递归实现链表的操作
- add
- get
- set
- contains
- remove
class Node{
E e;
Node next,prev;
}
class Node{
E e;
Node next,prev;
}
class Node{
E e;
int next;
}
Leetcode 206. Reverse Linked List
- 非递归
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
初步 | 1-2 |
---|---|
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null)
return head;
ListNode rev = reverseList(head.next);
head.next.next = head;
head.next = null;
return rev;
}
- 08-MergeSort
08-1-MergeSort
08-2-MergeSort-Track
08-3-MergeSort-Complexity
08-4-MergeSort-Basic-Optimization
08-5-MergeSort-Advanced-Optimization
08-6-MergeSort-Memory-Optimization
08-7-Bottom-Up
08-8-Bottom-Up-Optimization
08-9-Reverse-Pairs
算法模板:
MergerSort(arr,l,r){
if(l >= r) return;
int mid = (l + r) / 2;
// 对arr[l,mid]进行排序
MergerSort(arr,l,mid);
// 对arr[mid+1,r]进行排序
MergerSort(arr,mid+1,r);
//将arr[l,mid]和arr[mid+1,r]合并
merge(arr,l,mid,r);
}
打印跟踪
- 优化一(增加判断)
if (arr[mid].compareTo(arr[mid + 1]) > 0)// arr[mid] < arr[mid + 1],
merge(arr, l, mid, r);
同其他排序(选择排序、插入排序)比较
随机数组 | 有序数组 |
---|---|
优化前后自身比较
随机数组 | 有序数组 |
---|---|
- 优化二(插入排序)
在优化一的基础上测试
if (arr[mid].compareTo(arr[mid + 1]) > 0)// arr[mid] < arr[mid + 1],
merge(arr, l, mid, r);
同其他排序(选择排序、插入排序)比较
随机数组 | 有序数组 |
---|---|
优化前后自身比较
随机数组 | 有序数组 |
---|---|
- 优化三(临时空间)
在优化一、二的基础上测试
E[] temp = Arrays.copyOf(arr, arr.length);
...
System.arraycopy(arr, l, temp, l, r - l + 1);
int i = l, j = mid + 1;
for (int k = l; k <= r; k++) {
if (i > mid)
arr[k] = temp[j++];
else if (j > r)
arr[k] = temp[i++];
else if (temp[i].compareTo(temp[j]) <= 0)
arr[k] = temp[i++];
else
arr[k] = temp[j++];
}
同其他排序(选择排序、插入排序)比较
随机数组 | 有序数组 |
---|---|
优化前后自身比较
随机数组 | 有序数组 |
---|---|
public static <E extends Comparable<E>> void sortBU(E[] arr) {
int n = arr.length;
E[] temp = Arrays.copyOf(arr, n);
for (int size = 1; size < n; size += size) {
// Merge [i , i + sz -1] and [i + sz , min(i + 2 * sz -1 , n - 1)]
for (int i = 0; i + size < n; i += 2 * size)
merge(arr, i, i + size - 1, Math.min(i + 2 * size - 1, n - 1), temp);
}
}
6 4 2 3 1 5
- size = 1(i < 5)
- i = 0
- [0] [1]
merge(arr, 0, 0, 1, temp);
- [0] [1]
- i = 2
- [2] [3]
merge(arr, 2, 2, 3, temp);
- [2] [3]
- i = 4
- [4] [5]
merge(arr, 4, 4, 5, temp);
- [4] [5]
- i = 0
4 6 2 3 1 5
- size = 2(i < 4)
- i = 0
- [0,1] [2,3]
merge(arr, 0, 1, 3, temp);
- [0,1] [2,3]
- i = 0
2 3 4 6 1 5
- size = 4(i < 2)
- i = 0
- [0,3] [4,5]
merge(arr, 0, 3, 5, temp);
- [0,3] [4,5]
- i = 0
1 2 3 4 5 6
public static <E extends Comparable<E>> void sortBU2(E[] arr) {
int n = arr.length;
E[] temp = Arrays.copyOf(arr, n);
for (int i = 0; i < n; i += K + 1)
InsertionSort.sort(arr, i, Math.min(n - 1, i + K));
for (int size = K + 1; size < n; size += size) {
// Merge [i , i + sz -1] and [i + sz , min(i + 2 * sz -1 , n - 1)]
for (int i = 0; i + size < n; i += 2 * size) {
int l = i, mid = i + size - 1, r = Math.min(i + 2 * size - 1, n - 1);
merge(arr, l, mid, r, temp);
}
}
}
- 09-Quick-Sort
09-1-QuickSort
09-2-QuickSort-Optimized-by-Random
09-3-QuickSort-2-Ways
09-4-QuickSort-3-Ways
09-5-Sort-Colors
09-6-Select-K
对于有序数组:
时间复杂度:
递归深度:
随机选择(选中最小值):
Leetcode 215. Kth Largest Element in an Array
- 10-Binary-Search
10-1-Recursive-Binary-Search
10-2-Binary-Search
10-3-Select-K-Non-Recursive
10-4-Another-Recursive-Binary-Search
10-5-Another-Binary-Search
10-6-Another-Select-K
10-7-Another-MergeSort
10-8-Upper
10-9-Upper-Ceil
10-10-Lower-Ceil
10-11-Lower
10-12-Lower-Floor
10-13-Upper-Floor
10-14-Koko-Eating-Bananas
10-15-Capacity-To-Ship-Packages-Within-D-Days
public static <E extends Comparable<E>> int search(E[] data, E target) {
int l = 0, r = data.length - 1;
while(l <= r){
int mid = l + (r - l) / 2;
if(data[mid].compareTo(target) == 0)
return mid;
if(data[mid].compareTo(target) < 0)
l = mid + 1;
else
r = mid - 1;
}
return -1;
}
public static <E extends Comparable<E>> int searchR(E[] data, E target) {
return searchR(data, 0, data.length - 1, target);
}
private static <E extends Comparable<E>> int searchR(E[] data, int l, int r, E target) {
if (l > r) return -1;
int mid = l + (r - l) / 2;
if (data[mid].compareTo(target) == 0)
return mid;
if (data[mid].compareTo(target) < 0)
return searchR(data, mid + 1, r, target);
return searchR(data, l, mid - 1, target);
}
包括递归与非递归
public static <E extends Comparable<E>> int search(E[] data, E target) {
int l = 0, r = data.length;
while (l < r) {
int mid = l + (r - l) / 2;
if (data[mid].compareTo(target) == 0)
return mid;
if (data[mid].compareTo(target) < 0)
l = mid + 1;// [mid + 1 , r)
else
r = mid;// [l , mid)
}
return -1;
}
public static <E extends Comparable<E>> int searchR(E[] data, E target) {
return searchR(data, 0, data.length, target);
}
private static <E extends Comparable<E>> int searchR(E[] data, int l, int r, E target) {
if (l >= r) return -1;
int mid = l + (r - l) / 2;
if (data[mid].compareTo(target) == 0)
return mid;
if (data[mid].compareTo(target) < 0)
return searchR(data, mid + 1, r, target);// [mid + 1 , r)
return searchR(data, l, mid, target);// [l , mid)
}
修改区间
- 数组中存在
$target$ ,返回最大索引 - 数组中不存在
$target$ ,返回$upper$
- 数组中存在
$target$ ,返回最小索引 - 数组中不存在
$target$ ,返回$upper$
指标量 | 存在(5) | 不存在(6) |
---|---|---|
1 1 3 3 5 5 7 7(6) | 1 1 3 3 5 5 7 7(6) | |
1 1 3 3 5 5 7 7(5) | 1 1 3 3 5 5 7 7(6),同 |
|
1 1 3 3 5 5 7 7(4) | 1 1 3 3 5 5 7 7(6),同 |
图解(存在部分)
指标量 | 1 1 3 3 5 5 7 7(5) |
---|---|
- 数组中存在
$target$ ,返回最小索引 - 数组中不存在
$target$ ,返回$lower$
- 数组中存在
$target$ ,返回最大索引 - 数组中不存在
$target$ ,返回$lower$
指标量 | 存在(5) | 不存在(6) |
---|---|---|
1 1 3 3 5 5 7 7(3) | 1 1 3 3 5 5 7 7(5) | |
1 1 3 3 5 5 7 7(4) | 1 1 3 3 5 5 7 7(5),同 |
|
1 1 3 3 5 5 7 7(5) | 1 1 3 3 5 5 7 7(5),同 |
图解(存在部分)
指标量 | 1 1 3 3 5 5 7 7(5) |
---|---|
- 校正
$r$ ,上取整$mid = l + (r - l + 1) / 2;$
1011. Capacity To Ship Packages Within D Days
部分解释:
private int costDays(int[] weights, int k) {
int cur = 0, res = 0;// 0
for (int weight : weights)
if (cur + weight <= k) cur += weight;// 1
else {// 2
res++;
cur = weight;
}
res++;// 3
return res;
}
步骤 | weight | cur | res |
---|---|---|---|
0 | 0 | 0 | |
1 | 1 | 1 | 0 |
1 | 2 | 3 | 0 |
1 | 3 | 6 | 0 |
1 | 4 | 10 | 0 |
1 | 5 | 15 | 0 |
2 | 6 | 6 | 1 |
1 | 7 | 13 | 1 |
2 | 8 | 8 | 2 |
3 | 9 | 9 | 3 |
4 |
- 11-Binary-Search-Tree
11-1-Binary-Search-Tree
11-2-Add-Elements
11-3-Improved-Add-Elements
11-4-Contains-Element
11-5-PreOrder-Traverse-in-BST
11-6-InOrder-Traverse-in-BST
11-7-PostOrder-Traverse-in-BST
11-8-Non-Recursion-Preorder-Traverse-in-BST
11-9-Non-Recursion-Inorder-Traverse-in-BST
11-10-Non-Recursion-Postorder-Traverse-in-BST
11-11-Level-Traverse-in-BST
11-12-Remove-Min-and-Max
11-13-Remove-Elements
11-14-Floor-and-Ceil-in-BST
11-15-Rank-and-Select
11-16-Set
11-16-1-BSTSet
11-16-2-LinkedListSet
11-16-3-Time-Complexity-of-Set
11-16-4-Unique-Morse-Code-Words
11-17-Map
11-17-1-BSTMap
11-17-2-LinkedList
11-17-3-Time-Complexity-of-Map
11-17-4-Intersection-of-Two-Arrays
11-17-5-Intersection-of-Two-Arrays-II
相关术语:
根节点
叶子节点
左孩子/右孩子
树具有天然的递归结构(每个节点的左子树也是二叉树、每个节点的右子树也是二叉树)
二分搜索树:二叉树的一种。
-
二叉树;
-
每一个节点的值;
- 大于其左子树的所有节点的值。
- 小于其右子树的所有节点的值。
-
每一颗子树也是二分搜索树。
封装属于我们的二叉搜索树:
private class Node {
public E e;
public Node left, right;
public Node(E e) {
this.e = e;
left = null;
right = null;
}
@Override
public String toString() {
return e.toString();
}
}
private Node root;
private int size;
BST()
boolean isEmpty()
void add(E e)
boolean contains(E e)
void preOrder(Node node)
void pretOrder(Node node)
void preOrderNR()
void inOrder()
void inOrder(Node node)
void inOrderNR()
void postOrder()
void postOrder(Node node)
void postOrderNR()
void levelOrder()
E minimum()
Node minimum(Node node)
E removeMin()
Node removeMin(Node node)
E maximum()
Node maximum(Node node)
E removeMax()
Node removeMax(Node node)
void remove(E e)
Node remove(Node node, E e)
E floor(E e)
Node floor(Node node, E e)
E ceil(E e)
ceil(Node node, E e)
int rank(E e)
int rank(Node node, E e)
E select(int index)
E select(Node node, int index)
- 增加元素(递归算法)
非递归
public void add(E e) {
if (root == null) {
root = new Node(e);
size++;
return;
}
Node p = root;
while (p != null) {
if (e.compareTo(p.e) < 0) {
if (p.left == null) {
p.left = new Node(e);
size++;
return;
}
p = p.left;
} else if (e.compareTo(p.e) > 0) {
if (p.right == null) {
p.right = new Node(e);
size++;
return;
}
p = p.right;
} else return;
}
}
- 查找元素(递归算法)
-
前序遍历
5 3 2 4 6 8
-
中序遍历
2 3 4 5 6 8
-
后序遍历
2 4 3 8 6 5
非递归实现(基于栈)
- 删除元素
$floor:< e,max$ $ceil:> e,min$
$rank$ - $select$
增加一个域
关于 $select$ 的样例演示,选择
方法 | 大小关系 | ||
---|---|---|---|
$select(【41】,4)$ | |||
$select(【58】,1)$ | |||
$select(【42】,1)$ | = |
基于二分搜索树封装属于我们的集合 & 基于链表封装属于我们的集合:
void add(E e);
boolean contains(E e);
void remove(E e);
int getSize();
boolean isEmpty();
二者比较
计算
得到
操作 |
|
|
---|---|---|
add(E e) |
||
contains(E e) |
||
remove(E e) |
||
getSize() |
||
isEmpty() |
同样的数据对应不同的二分搜索树,意味着
$BSTSet$ 可能退化为$LinkListSet$ ,此时的时间复杂度也增加到$\mathrm{O}(n)$ 。
- 有序集合中的元素具有顺序性——基于搜索树的实现
- 无序集合中的元素没有顺序性——基于哈希表的实现(截止目前使用链表实现)
基于二分搜索树封装属于我们的映射 & 基于链表封装属于我们的映射:
void add(K key, V value);
V remove(K key);
boolean contains(K key);
V get(K key);
void set(K key, V newValue);
int getSize();
boolean isEmpty();
二者比较
操作 |
|
|
---|---|---|
add(K key, V value) |
||
remove(K key) |
||
contains(K key) |
||
get(K key) |
||
set(K key, V newValue) |
||
getSize() |
||
isEmpty() |
同样的数据对应不同的二分搜索树,意味着
$BSTMap$ 可能退化为$LinkListMap$ ,此时的时间复杂度也增加到$\mathrm{O}(n)$ 。
- 有序映射中的键具有顺序性——基于搜索树的实现
- 无序映射中的键没有顺序性——基于哈希表的实现(截止目前使用链表实现)
349. Intersection of Two Arrays
350. Intersection of Two Arrays II
- 12-Heap
12-1-Max-Heap
12-2-Heap-Sort
12-3-Replace-in-Heap
12-4-Heapify-in-Heap
12-5-Heap-Sort-Optimized
12-6-Min-Heap
实现优先队列的方式以及时间复杂度
数据结构 | 入队 | 出队 |
---|---|---|
普通线性结构 | ||
顺序线性结构 | ||
堆 |
二叉堆(Binary Heap):堆的一种实现。
- 完全二叉树
- 堆中某个节点的值总是不大于其父节点的值,父节点 >=子节点(最大堆)
- 堆中某个节点的值总是不小于其父节点的值,父节点 <=子节点(最小堆)
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
- | 62 | 41 | 30 | 28 | 16 | 22 | 13 | 19 | 17 | 15 |
父节点 -> 子节点
left child (i) = 2 * i
right child (i) = 2 * i + 1
子节点 -> 父节点
parent (i) = i / 2
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
62 | 41 | 30 | 28 | 16 | 22 | 13 | 19 | 17 | 15 |
父节点 -> 子节点
left child (i) = 2 * i + 1
right child (i) = 2 * (i + 1)
子节点 -> 父节点
parent (i) = (i - 1) / 2
采用这一种方式
- 元素上浮
- 元素下沉
非原地排序,创建了一个堆,增加了时间
- 最大元素替换
replace
:取出最大元素,放入新元素。
思路:直接替换堆顶元素,再 Sift Down
- 将任意数组整理为堆
Heapify
思路:找到倒数第一个非叶子节点,依次向上执行 Sift Down