算法基础提升——随机池结构问题、布隆过滤器、一致性Hash算法、岛问题、并查集实现

package com.zuoshen.jichutisheng.class01; import java.util.HashMap; import java.util.List; import java.util.Stack; /** * @author ShiZhe * @create 2022-03-15 12:36 */ public class code01 { /** * Insert、delete和getRandom方法的时间复杂度都是O(1) * @param <K> */ public static class Pool<K> { // 加入不重复 public HashMap<K, Integer> keyIndexMap; // 随机返回 public HashMap<Integer, K> indexKeyMap; public int size; /** * 无参构造函数 */ public Pool() { this.keyIndexMap = new HashMap<K, Integer>(); this.indexKeyMap = new HashMap<Integer, K>(); this.size = 0; } /** * 插入不重复 * @param key */ public void insert(K key) { if (!this.keyIndexMap.containsKey(key)) { this.keyIndexMap.put(key, this.size); this.indexKeyMap.put(this.size++, key); } } /** * 获得需要删除的key与对应的位置 * 获得最后一个的值,size减1 * 用最后一个替换删除key的下标 * 删除key * @param key */ public void delete(K key) { if (this.keyIndexMap.containsKey(key)) { int deleteIndex = this.keyIndexMap.get(key); int lastIndex = --this.size; K lastKey = this.indexKeyMap.get(lastIndex); this.keyIndexMap.put(lastKey, deleteIndex); this.indexKeyMap.put(deleteIndex, lastKey); this.keyIndexMap.remove(key); this.indexKeyMap.remove(lastIndex); } } /** * 随机返回 * @return */ public K getRandom() { if (this.size == 0) { return null; } int randomIndex = (int) (Math.random() * this.size); // 0 ~ size -1 return this.indexKeyMap.get(randomIndex); } } /** * https://developer.aliyun.com/article/773205 * 布隆过滤器:主要用于判断一个元素是否在一个集合中。 * BloomFilter 是由一个固定大小的二进制向量或者位图(bitmap)和一系列映射函数组成的。 * 一个元素如果判断结果为存在的时候元素不一定存在,但是判断结果为不存在的时候则一定不存在。 * 布隆过滤器可以添加元素,但是不能删除元素。因为删掉元素会导致误判率增加。 */ /** * https://zhuanlan.zhihu.com/p/482549860 * 一致性Hash算法原理:一致性哈希算法在是一种特殊的哈希算法,在移除或者添加一个服务器时, * 能够尽可能小地改变已存在的服务请求与处理请求服务器之间的映射关系; * 一致性哈希解决了简单哈希算法在分布式哈希表(Distributed Hash Table,DHT)中存在的动态伸缩等问题; * 一致性Hash就是:将原本单个点的Hash映射,转变为了在一个环上的某个片段上的映射! */ /** * 岛问题 * @param m */ public static int countIslands(int[][] m) { if (m == null || m[0] == null) { return 0; } // int N = m.length; // int M = m[0].length; int res = 0; for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { if (m[i][j] == 1) { res++; infect(m, i, j, N, M); } } } return res; } public static void infect(int[][] m, int i, int j, int N, int M) { if (i < 0 || i >= N || j < 0 || j >= M || m[i][j] != 1) { return; } m[i][j] = 2; infect(m, i + 1, j, N, M); infect(m, i - 1, j, N, M); infect(m, i, j + 1, N, M); infect(m, i, j - 1, N, M); } /** * https://zhuanlan.zhihu.com/p/93647900 * 并查集节点结构 * @param <V> */ public static class Element<V> { public V value; public Element(V value) { this.value = value; } } /** * 并查集实现 * @param <V> */ public static class UnionFindSet<V> { // 元素编号 public HashMap<V, Element<V>> elementMap; // 元素指向父节点 public HashMap<Element<V>, Element<V>> fatherMap; // 元素所在集合的深度 public HashMap<Element<V>, Integer> rankMap; /** * 初始化 * @param list */ public UnionFindSet(List<V> list) { elementMap = new HashMap<>(); fatherMap = new HashMap<>(); rankMap = new HashMap<>(); for (V value : list) { Element<V> element = new Element<V>(value); elementMap.put(value, element); // 指向自己 fatherMap.put(element, element); // 深度为1 rankMap.put(element, 1); } } /** * 寻找父节点 * @param element * @return */ private Element<V> findHead(Element<V> element) { Stack<Element<V>> path = new Stack<>(); // 遍历得到父节点,放入栈中 while (element != fatherMap.get(element)) { path.push(element); element = fatherMap.get(element); } // 降低深度,直接指向头节点 while (!path.isEmpty()) { fatherMap.put(path.pop(), element); } // 最终父节点 return element; } /** * 通过判断父节点是否相同来判断2元素是否在同一集合中 * @param a * @param b * @return */ public boolean isSameSet(V a, V b) { if (elementMap.containsKey(a) && elementMap.containsKey(b)) { return findHead(elementMap.get(a)) == findHead(elementMap.get(b)); } return false; } /** * 合并,合并合的是头结点 * @param a * @param b */ public void union(V a, V b) { if (elementMap.containsKey(a) && elementMap.containsKey(b)) { Element<V> aF = findHead(elementMap.get(a)); Element<V> bF = findHead(elementMap.get(b)); if (aF != bF) { // 获取2个集合的深度 Element<V> big = rankMap.get(aF) >= rankMap.get(bF) ? aF : bF; Element<V> small = big == aF ? bF : aF; // 小深度头结点指向大深度头结点 fatherMap.put(small, big); // 深度+1 rankMap.put(big, rankMap.get(big) + 1); rankMap.remove(small); } } } } /** * 主函数 * @param args */ public static void main(String[] args) { // hashMap的应用 Pool<String> pool = new Pool<String>(); pool.insert("11"); pool.insert("22"); pool.insert("33"); System.out.println(pool.getRandom()); pool.delete("11"); pool.delete("22"); pool.delete("33"); System.out.println(pool.getRandom()); // 岛问题 int[][] m1 = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 1, 0, 1, 1, 1, 0 }, { 0, 1, 1, 1, 0, 0, 0, 1, 0 }, { 0, 1, 1, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 1, 1, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }; System.out.println(countIslands(m1)); int[][] m2 = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 1, 1, 1, 1, 1, 0 }, { 0, 1, 1, 1, 0, 0, 0, 1, 0 }, { 0, 1, 1, 0, 0, 0, 1, 1, 0 }, { 0, 0, 0, 0, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 1, 1, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }; System.out.println(countIslands(m2)); } }

 


__EOF__

本文作者北漂的尘埃
本文链接https://www.cnblogs.com/shizhe99/p/16047440.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   北漂的尘埃  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
点击右上角即可分享
微信分享提示