算法学习 期末总结

数据结构

  • 一维:
    • 基础:数组 vector(string),链表 linked list
    • 高级:栈 stack,队列 queue,双端队列 deque,集合 set, 映射 map, 优先队列 priority_queue
  • 二维:
    • 基础:树 tree, 图 graph
    • 高级: 二叉搜索树 binary search tree(red-black tree, AVL),堆heap,并查集 disjoint set, 字典树 Trie
  • 特殊:
    • 位运算 Bitwise, 布隆过滤器 BloomFilter
    • LRU Cache

时间复杂度

在这里插入图片描述
在这里插入图片描述

算法

  • if-else, switch -> branch
  • for, while loop -> Iteration
  • 递归 Recursion (Divide & Conquer, Backtrace)
  • 搜索 Search:深度优先搜索 Depth first search,广度优先搜索 Breadth first search,A*
  • 动态规划 Dynamic Programming
  • 二分查找 Binary Search
  • 贪心 Greedy
  • 数学 Math, 几何 Geometry

模板

  • 递归
void recursion(level, param1, param2, ...)
{
	//recursion terminator
	if(level > MAX_LEVEL)
	{
		process_result();
		return;
	}
	
	//process logic in current level
	process(level, data...);
	
	//drill down
	recursion(level + 1, p1, ...);
	
	//reverse the current level status if needed
}
  • 分治
void divide_conquer(problem, param1, param2, ...): 
  // recursion terminator 
  if problem is None: 
	print_result 
	return 
  // prepare data 
  data = prepare_data(problem) 
  subproblems = split_problem(problem, data) 
  // conquer subproblems 
  subresult1 = self.divide_conquer(subproblems[0], p1, ...) 
  subresult2 = self.divide_conquer(subproblems[1], p1, ...) 
  subresult3 = self.divide_conquer(subproblems[2], p1, ...)// process and generate the final result 
  result = process_result(subresult1, subresult2, subresult3,)
	
  // revert the current level states

  • DFS
void dfs(Node* node, unordered_set<Node*>& visited)
{
	if(visited.count(node) > 0)
		return ;
	visited.insert(node);
	for(auto &child: node->children)
	{
		if(visited.count(child) < 1)
			dfs(child, visited);
	}
}
  • BFS
def bfs(graph, start, end)
{
	visited = set();
	queue = [];
	queue.append([start])
	
	while queue:
		node = queue.pop()
		visited.add(node)
		
		process(node)
		nodes = generate_related_nodes(node)
		queue.push(nodes)
}
  • 归并排序
void mergeSort(vector<int>& nums, int left, int right)
{
	if(left > right)
		return;
	int mid = ((left + right) >> 1);
	mergeSort(nums, left, mid);
	mergeSort(nums, mid + 1, right);
	merge(nums, left, mid, right);
}

void merge(vector<int>& nums, int left, int mid, int right)
{
	vector<int> temp(right - left + 1);
	int i = left, j = mid + 1, k = 0;
	while(i <= mid && j <= right)
		temp[k++] = nums[i] <= nums[j] ? nums[i++] : nums[j++];
	while(i <= mid) temp[k++] = nums[i++]; //如果左侧数组没用完
	while(j <= right) temp[k++] = nums[j++]; //如果右侧数组没用完
	for(int p = 0; p < temp.size(); p++)
		nums[left + p] = temp[p];
}
  • 快速排序
void quickSort(vector<int>& nums, int begin, int end)
{
	if(begin > end)
		return ;
	int pivot = partition(nums, begin, end);
	quickSort(nums, begin, pivot - 1);
	quickSort(nums, pivot + 1, end);
}
int partition(vector<int>& nums, int begin, int end)
{
	int pivot = end, counter = begin;
	for(int i = begin, i < end; i++)
	{
		if(nums[i] < nums[pivot])
			swap(nums[counter++], nums[i]);
	}
	swap(nums[counter], nums[pivot]);
	return counter;
}
  • 堆排序
void heapSort(vector<int>& nums)
{
	priority_queue<int, vector<int>, greater<int>> pq;
	for(int i = 0; i < nums.size(); i++)
		pq.push(nums[i]);
	for(int i = 0; i < nums.size(); i++)
		nums[i] = pq.pop();
}

学习要点

  • 基本功是区别业余和职业选手的根本。 深厚功底来自于–过遍数
  • 最大的误区: 只做一遍
  • 五毒神掌
  • 刻意练习–练习缺陷弱点地方、不舒服、枯燥,但是这些都是成长的基础
  • 反馈–看题解、看国际版的高票回答

经典习题

需要多次练习彻底掌握的习题:
爬楼梯、硬币兑换
括号生成、括号匹配、直方图最大面积、滑动窗口
二叉树遍历、分层输出树、判断二叉排序树
股票买卖、偷房子、字符串编辑距离、最长上升子序列、最长公共子序列
异位词(判断和归类)、回文串(最大回文串)、regex和通配符匹配
高级数据结构(Trie、BloomFilter、LRU cache)

五毒神掌

第一遍: 不要死磕,要看代码学习(一定要看国际版的高票回答)
第二遍:自己写
第三遍:24小时后
第四遍:一周后
第五遍:面试前

面试技巧

  1. Clarfication:明确题目意思、边界、数据规模
  2. Possible solutions:穷尽所有可能的解法
    • compare time 、space
    • optimal solution
  3. Coding:代码简洁、高性能、美感
    N皇后问题
  4. Test cases
  • N皇后位运算解法
class Solution {
public:
    int totalNQueens(int n) {
        dfs(n, 0, 0, 0, 0);
        
        return this->res;
    }
    
    void dfs(int n, int row, int col, int ld, int rd) {
        if (row >= n) { res++; return; }
        
        // 将所有能放置 Q 的位置由 0 变成 1,以便进行后续的位遍历
        int bits = ~(col | ld | rd) & ((1 << n) - 1);
        while (bits > 0) {
            int pick = bits & -bits; // 注: x & -x
            dfs(n, row + 1, col | pick, (ld | pick) << 1, (rd | pick) >> 1);
            bits &= bits - 1; // 注: x & (x - 1)
        }
    }


private:
    int res = 0;
};
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值