labuladong的算法小抄读书笔记-第一章语言基础
一、C++中的容器
C++的函数参数默认是传值的,如果使用容器作为参数,一般会加上 & 作为传引用。
1.1 动态数组vector
由标准库封装的数组容器,可自动扩容、缩容,int[]声明数组更加高级。
初始化方法:
1 2 3 4 5 6 7 8 9 10 11 12 13
| int n = 7, m =8;
vector<int> nums;
vector<int> nums(n);
vector<int> nums{1, 3, 5};
vector<int> nums(n, 2);
vector<vector<int>> dp;
vector<vector<bool>> dp(m, vector<boo>(n, true));
|
成员函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| bool empty();
size_type size();
reference back();
void push_back(const value_type& val);
void pop_back();
|
1.2 字符串string
初始化方法
1 2 3 4
| string s;
string s = "abc";
|
成员函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| size_t size();
bool empty();
void push_back(char c);
void pop_back();
string substr(size_t pos, size_t len);
|
1.3 哈希表unordered_map
初始化方法
1 2 3 4 5
| unordered_map<int, int> mapping;
unordered_map<string, vector<int>> mapping;
|
成员函数
1 2 3 4 5 6 7 8 9 10 11
| size_type size();
bool empty();
size_type count count(const key_type& key);
size_type erase(const key_type& key);
|
1.4 哈希集合unordered_set
初始化方法
1 2 3 4 5
| unordered_set<int> visited;
unordered_set<string> visited;
|
成员函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| size_type size();
bool empty();
size_type count(const key_type& key);
pair<iterator, bool> insert(const key_type& key);
size_type erase(const key_type& key);
|
1.5 队列queue
初始化方法
1 2 3 4 5
| queue<int> q;
queue<string> q;
|
成员函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| bool empty();
size_type size();
void push(const value_type& val);
value_type& front();
void pop();
|
C++中一般pop都是void类型,不会在删除的同时将元素返回
1.6 堆栈stack
初始化方法
1 2 3 4 5
| stack<int> stk;
stack<string> stk;
|
成员函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| bool empty();
size_type size();
void push(const value_type& val);
value_type& top();
void pop();
|
二、Java中容器
Java此处略过,本人对Java相对熟悉,不再赘述
三、Python3中的容器
列表list可以作为数组,可以作为堆栈,也可以作为队列使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| arr = [1, 2, 3, 4]
print(arr[2])
arr.append(5)
print(arr[-1])
stack = []
stack.append(1) stack.append(2)
e1 = stack.pop()
e2 = stack[-1]
|
元组tuple和字典dict
1 2 3 4 5 6 7 8 9 10 11
| memo = dict()
def dp(i, j): if (i, j) in memo: return memo[(i, j)] memo[(i,j)] = 。。。 return memo[(i,j)]
|
四、算法的框架思维
4.1 存储方式
数据结构的底层存储方式只有两种:数组(顺序存储)和链表(链式存储)
4.2 基本操作
对任何数据结构,操作无非遍历+访问,再具体就是增、删、查、改
各种数据结构的访问+遍历无非两种形式:线性和非线性
线性遍历以for/while为代表,非线性以递归为代表。
数据遍历框架,是典型的线性迭代结构:
1 2 3 4 5
| void traverse(int[] arr) { for (int i = 0; i < arr.length: i++) { } }
|
链表遍历框架,兼具迭代和递归结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class ListNode { int val; ListNode next; } void traverse(ListNode head) { for (ListNode p = head; p != null; p = p.next) { } }
void traverse(ListNode head) { traverse(head.next); }
|
如在前序遍历处打印head.val就是正序打印链表,在后序遍历处打印head.val就是倒序打印链表
二叉树遍历框架,是典型的非递归遍历结构
1 2 3 4 5 6 7 8 9 10 11 12 13
| class TreeNode { int val; TreeNode left, right; }
void traverse(TreeNode root) { traverse(root.left); traverse(root.right); }
|
这里可以进一步扩展到N叉树的遍历过程
1 2 3 4 5 6 7 8 9 10 11
| class TreeNode { int val; TreeNode[] children; }
void traverse(TreeNode root) { for (TreeNode child : root.children) { traverse(child); } }
|
4.3 刷题指南
从二叉树开始刷起训练框架思维
Leetcode-124( 二叉树中的最大路径和)
Leetcode-105(从前序与中序遍历序列构造二叉树)
Leetcode-99(恢复二叉搜索树)