左神算法讲堂笔记 07并查集和前缀树

左神算法讲堂笔记 07并查集和前缀树_第1张图片
只分析多线程下如何优化。
假设把矩阵分成两块,交给两个线程去处理。那么各自跑完会在地图上标注**当前的1属于哪个中心点(多线程间全局变量可以使用volatile关键字)
左神算法讲堂笔记 07并查集和前缀树_第2张图片

先站在左边一方的角度考虑,只需要把边界上的1,即图上的A位置。接着向右边进行询问,由于右边的格子上是1,那么就把AC进行合并(使用并查集进行优化),岛的数量-1。 下一次遇到AC的时候,并查集查询到属于同一个集合,那么就不进行操作。

总结一下,
第一步:进行区域划分,交给不同的线程去执行dfs,并且标注扩散源,得到初始tot岛数量。
第二步:针对边界进行合并,合并通过并查集。合并两个区域就让tot-1。

并查集代码


import java.util.HashMap;
import java.util.List;


public class UnionFindSet {
    static class Node{

    }
    public HashMap fatherMap;
    public HashMap sizeMap;

    public UnionFindSet(Listlist){
        makeSets(list);
    }

    private void makeSets(List list) {
        fatherMap.clear();
        sizeMap.clear();
        for(Node node:list){
            fatherMap.put(node,node);
            sizeMap.put(node,1);
        }
    }
    Node findHead(Node node){
        while (fatherMap.get(node) != node){
            node = fatherMap.get(node);
        }
        return node;
    }
    public boolean isSameSet(Node a, Node b){
        return findHead(a) == findHead(b);
    }
    public void union(Node a,Node b){
        if(a == null || b == null)
            return;
        Node aHead = findHead(a);
        Node bHead = findHead(b);
        if (aHead != bHead) {
            int aSetSize= sizeMap.get(aHead);
            int bSetSize = sizeMap.get(bHead);
            if (aSetSize <= bSetSize) {
                fatherMap.put(aHead, bHead);
                sizeMap.put(bHead, aSetSize + bSetSize);
            } else {
                fatherMap.put(bHead, aHead);
                sizeMap.put(aHead, aSetSize + bSetSize);
            }
        }
    }
}

前缀树

https://blog.csdn.net/qq_37591656/article/details/87896097#comments 牛客网的项目总结中已经有源代码,这里就当复习。

1、数据结构

class TrieNode{
	// 根节点,前缀树的入口,val为空
	private TrieNode rootNode = new TrieNode();
	// 根节点的子结点们
	private Map subNodes = new HashMap<>();
	// 结束标志
	int end;
	// 前缀数量,用于删除
	int path;
}

2、插入(String word)

从根节点root = rootNode出发,遍历word的每个字符,如果root的子节点中包含了当前字符,那么root = root.subNodes.get© ; 否则在root下新建一个TrieNode。经过每个结点时 root.path++,为了方便后面的删除

3、查询(String word)

从根节点root = rootNode出发,指针p1、p2初始化时都指向word的起点。当p2所指的位置在root的subNode中存在,就询问end是否为1,如果是1标明找到,递推到下一轮;如果root中的end==0,那么进行下一层查找,p2++, root = root.subNode.get(word[ p2 ])。 当root的subNodes不存在p2,那么查找失败,p1++,p2++, root = rootNode。

4、删除(String word)

从根节点开始查找word,每个结点的root.path–; 当遇到root.path减完==0,直接把root.subsNode.put(c,null);后面的直接可以删除

你可能感兴趣的:(算法讲堂)