济公学院算法笔记

算法学习

1.数据结构及应用

数据结构只是工具,用来解决问题的,因此要熟悉并选用对应的数据结构来解决实际问题。

  • 线性数据结构
  1. 可变数组-例如Java中的ArrayList、Deque

    队列:例如 BFS

    栈:例如两个栈模拟表达式或者无递归的DFS

    链表:插入排序或者并查集

  • 二分堆

​ 共有三种操作,getMin(复杂度为O(1)), deleteMin(复杂度为O(logn)), insert(复杂度为O(logn))。最经典的应用是堆排序,在Java中的实现方式是PriorityQueue。可以用作LRU,在面试中可以用BST来代替map操作

  • 二分搜索树(BST)

​ 在Java中的应用主要是TreeSet和TreeMap,跟HashTable不一样,HashTable不是有序的。BST能实现二分堆的所有内容,就只是getMin()方法效率会低一点。非常适合用于找某值最近的两个数。其他应用:查询(滑动窗口)kth的值(用两个BST或有迭代器的BST实现)

  • 前缀树(Trie)

​ 目标是查询动态词典,如果是静态词典,可以用二分查找

  • 后缀树和后缀数组
  • 统计一个范围内相关的数据,比如一个范围内的和,一个范围内的所有值的最小值、抑或等等,可以用二分统计树等等,相当于打标签

2.图上的深度和广度优先搜索

1.隐式图上的搜索模型

  • 隐式图:从起点可到达的状态(顶点)在搜索开始前未知
  • Depth-First Search:从起点找到一个或者所有的终结状态,空间复杂度取决于最大深度会不会导致堆栈溢出
  • Breadth-First Search:从起点找到一个最近的终结状态,不一定要用queue,也可以试试用ArrayList,空间复杂度取决于一层的最大宽度

2.DFS template

  • DFS的参数中状态和路径在前,常量在后
  • 在递归后注意恢复递归前的环境
dfs(current_state, path, constants){
    //mark visited
    visited[current_state] = true;
    
    //judge terminated
    if(is_terminate(current_state)){
        solution.add(path);
        return;
    }
    
    //loop actions
    for(next_state, action/edge in transition(current_state)){
        if(visited(next_state)) continue;
        path.push_back(action/edge);
        dfs(next_state, path, constants);
        path.pop_back();
    }
}

e.g.

class State{int Wa; int Wb;};

typedef enum(FILL_A, FILL_B, EMPTY_A, EMPTY_B, POUR_AB, POUR_BA) Action;

vector<pair<State, Action>> transition(State current_state){
    result.push_back(pair(State(Ca, current_state.Wb), FILL_A));
    result.push_back(pair(State(current_state.Wa, Cb), FILL_B));
}

3.BFS Template

bfs(start_state){
    queue.push(start_state);
    meta_data[start_state] = { 
    	visited = true, pre_state = node, pre_action = none
    };
    
    while(queue is not empty){
        current_state = queue.pop_front();
        if(is_terminate(current_state)){
            solution.add(path constructed from meta_data);
            return;
        }
        
        for(next_state, action/edge in transition(current_state)){
            if(meta_data[next_state].visited) continue;
            queue.push_back(next_state);
            meta_data[next_state] = {
                visited = true,
                pre_state = current_state,
                pre_action = action/edge
            };
        }
    }
}

BFS的扩展应用 - 0-1图上的最短路径,用两个queue(weight是0的形成一个queue,是1的形成另一个queue)或者deque(为0的放左边,为1的放右边)

4.搜索优化

  • 状态定义(e.g. high dimensional states 高维状态)和存储(e.g. Bitwise representation 使用位运算 or State Presenting combinations 多个参数组合表示状态)最优

  • transition过程是清晰和优化过的

  • 搜索顺序和剪枝(Pruning)的优化(e.g. A* or IDA*)

    1. DFS中朴素的剪枝

    2. BFS中的过河拆桥(避免BFS中的重复搜索 e.g.如果有一个顶点不满足条件,那这一类的顶点都可以不再继续考虑)

  • 部分记忆化搜索去避免重复搜索(DFS/BFS和记忆化搜索结合,与纯DP不同,因为DP可能内存不够)

  • 双向搜索

5.答疑

  • 不是所有可以DP的方法都能BFS

  • DP的状态转移一定是单向的有顺序的,不能有环

  • 搜索都解决不了太大规模的问题,因为是指数级的,一般用64位的整数就能表达所有问题

  • 显式图上(类似于一维数组二维数组)的dp就用简单的dp写循环,如果是隐式图上的dp就应该用dfs+memorization

  • 有时候最优解不需要所有状态,这时候也可以用dfs+memorization

  • 递归不如循环好调

3. 排序和二分搜索

1.排序算法

2. 拓扑排序

3. 二分搜索

posted @   快打球去吧  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示