第五课 哈希函数,哈希表,布隆过滤器,一致性哈希,岛问题,并查集结构

左程云算法初级班 第五课

  1. 认识哈希函数哈希表
    • 哈希函数的特点:1,相同输入、相同输出;2,不同输入、均匀分布;3,输入域无穷大;4,输出域有限;

    在这里插入图片描述

  2. 设计RandomPool结构

【题目】 设计一种结构,在该结构中有如下三个功能:insert(key):将某个key加入到该结构,做到不重复加入。delete(key):将原本在结构中的某个key移除。 getRandom():等概率随机返回结构中的任何一个key。【要求】 Insert、delete和getRandom方法的时间复杂度都是O(1)
在这里插入图片描述

  • 代码:
public static class Pool<K> {
     private HashMap<K, Integer> keyIndexMap;
     private HashMap<Integer, K> indexKeyMap;
     private int size;

     public Pool() {
         this.keyIndexMap = new HashMap<K, Integer>();
         this.indexKeyMap = new HashMap<Integer, K>();
         this.size = 0;
     }

     public void insert(K key) {
         if (!this.keyIndexMap.containsKey(key)) {
             this.keyIndexMap.put(key, this.size);
             this.indexKeyMap.put(this.size++, 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);
         }
     }

     public K getRandom() {
         if (this.size == 0) {
             return null;
         }
         int randomIndex = (int) (Math.random() * this.size); // 0 ~ size -1
         return this.indexKeyMap.get(randomIndex);
     }

 }

 public static void main(String[] args) {
     Pool<String> pool = new Pool<String>();
     pool.insert("zuo");
     pool.insert("cheng");
     pool.insert("yun");
     System.out.println(pool.getRandom());
     System.out.println(pool.getRandom());
     System.out.println(pool.getRandom());
     System.out.println(pool.getRandom());
     System.out.println(pool.getRandom());
     System.out.println(pool.getRandom());

 }
  1. 认识布隆过滤器

    • 其有一定的失信率;
    • 假如有一个黑名单,里面有100亿个url、每个url为64字节,那么存储这份黑名单需要640G,用布隆过滤器可减小很多内存;

    在这里插入图片描述

  2. 认识一致性哈希

在这里插入图片描述

  1. 认识并查集结构

    • 1,查2个元素是否属于同一个集合:isSameSet(A,B);2,2个元素各自所在的集合给合并在一起:union(A,B);

    在这里插入图片描述

    • 代码:
    public static class UnionFindSet {
        public HashMap<Node, Node> fatherMap;
        public HashMap<Node, Integer> sizeMap;
    
        public UnionFindSet() {
            fatherMap = new HashMap<Node, Node>();
            sizeMap = new HashMap<Node, Integer>();
        }
    
        public void makeSets(List<Node> nodes) {
            fatherMap.clear();
            sizeMap.clear();
            for (Node node : nodes) {
                fatherMap.put(node, node);
                sizeMap.put(node, 1);
            }
        }
    
        private Node findHead(Node node) {
            Node father = fatherMap.get(node);
            if (father != node) {
                father = findHead(father);
            }
            fatherMap.put(node, father);
            return father;
        }
        
        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);
                }
            }
        }
    }
    
  2. 岛问题

一个矩阵中只有0和1两种值,每个位置都可以和自己的上、下、左、右四个位置相连,如果有一片1连在一起,这个部分叫做一个岛,求一个矩阵中有多少个岛?
举例:
0 0 1 0 1 0
1 1 1 0 1 0
1 0 0 1 0 0
0 0 0 0 0 0
这个矩阵中有三个岛。

  • 使用感染函数,遍历函数时,遇到1便将与其同一个岛上的1都感染为2,同时岛数目加1,这样当感染完整个矩阵后,岛的数目便计算了出来;
  • 代码:
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);
 }
  • 若是数据量大,则可以考虑使用并查集结构,将大的矩阵划分多个小矩阵,然后记录小矩阵的岛数目以及边界信息。再使用并查集结构判断各个矩阵中那些岛在大矩阵是相连的,最后通过各个矩阵中的岛数目与相连的岛数目来求得大矩阵中的岛数目。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Timothy Cui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值