B站左程云算法视频基础提升01

哈希函数和哈希表

out(f(in))

1)in 无穷

out相对有限

2)same in 得出 same out(不随机)

3)dif in 得到same out (哈希碰撞)

4)均匀性,离散性

in 1                               out 1              m1

in 2           \overset{f}{\rightarrow}                out2     \overset{%m}{\rightarrow}      m2

in 3                               out3               m3

值在0-m-1,均匀分布

给一个范围0  -   2^{32}-1的无符号整数,一共有40亿个,给定1G内存,返回出现次数最多的。

当使用哈希表HashMap做时,key(int),四字节,Value四字节,8B*40亿=32G

最差情况:40亿个数全都不一样

思路:先哈希函数映射,然后在模上100,进行分类,对于每个小文件使用HashMap,从而得到每个小文件出现次数最大的数,再把这一百个数进行比较得到结果。

哈希表的扩容:N个str,扩容次数logN,每次扩容代价为N,所以总的扩容代价为O(N*logN),单次扩容代价logN,当K足够长时,逼近O(1),离线扩容技术不占用用户在线时间,进一步降低哈希表使用代价。

设计RandomPool结构

实现:insert(key):不重复插入key到该结构

delete(key):将原本在结构中的某个key移除

getRandom():等概率随机返回结构中的任何一个key

要求:时间复杂度都是o(1)

思路:准备map1:str——index 和  map2:index——str   和size

删除操作:将要删除的str,拿最后一个str去填补漏洞,size--(保证等概率)

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);
        return this.indexKeyMap.get(randomIndex);
    }
}

布隆过滤器

判断url是否在黑名单里:add,check,存在误判:白名单误判成黑名单,概率较低万分之一

位图(bit arr/ bit map)

int[100] 0~99  4字节= 32bit

long[100] 8字节=64bit

bit[] 每位1bit      100/8字节

方式:拿基础类型拼

int[] arr =new int[10];//32bit * 10 -> 320bits
//arr[0] int 0 ~ 31
//arr[1] int 32 ~ 63
//arr[2] int 64 ~ 95

int i =178;//想要取得178个bit的状态

int numIndex = 178 / 32;
int bitIndex = 178 % 32;

//拿到178位的状态
int s = ( (arr[numIndex] >> (bitIndex)) & 1);

//把178位的状态改为1
arr[numIndex] = arr[numIndex] | ( 1 << (bitIndex));

//改成0
 arr[numIndex] = arr[numIndex] & (~( 1 << bitIndex));

布隆过滤器就是一个大的位图 设m个bit 范围是0 ~ m-1

实际占用m/8字节

u1添加到黑名单,u1经过哈希函数f1再模上m得到k1,经过f2模上m得到k2,假设有k个哈希函数,得到k个位置,有可能一样也可能不一样,把这些位置全部描黑,接着u2,一直到u四十亿,黑名单集合建立好。查:某个url经过哈希函数模m后得到k个位置,如果位置全部为1,则是黑名单里的url。

k个hash有几个? m设为多少? K值极具增大时,会耗尽m,失误率增加

失误率:m 和 k

判断是否是布隆过滤器:是不是类似黑名单的系统且无删除行为,允许有失误率

和单样本的大小无关,只要哈希函数能接受这样的url就行

n =样本量 P=预期失误率

m = - \frac{n * lnP}{(ln2)^{2}}

k = ln2 * \frac{m}{n} \approx 0.7 * \frac{m}{n}   向上取整

P_{real} = (1 - e^{-\frac{n*k_{real}}{m_{real}}})^{k_{real}}

一致性哈希

hashkey的选择要选择种类较多的,使得高频、中频和低频都有数量

经典的数据库只需要在逻辑层部署,但在扩充数据端数量时,数据迁移的代价是全量的。

不用模的方式,保证数据迁移代价不高

把整个哈希域当作一个环

假设有三台机器,利用机器信息区分三台机器,机器信息经过哈希函数插入环中

查询时:经过哈希函数后,顺时针遇到的第一个机器

 逻辑端的每台机器存入机器哈希值的排序的有序数组,要查询的信息经过哈希函数后,做二分,找到大于等于其最左的位置。

每个机器管一段request

当增加机器的时候,数据迁移的代价减少

潜在问题:一开始机器少的时候如果均分环 2.增加减少机器时,负载不均衡

引入虚拟节点技术

m1分配1000个字符串

m2分配1000个字符串

m3也分配1000个字符串

分配的节点去抢环,按比例抢环

增加机器m4,该机器的节点去抢环

使得初始均衡和增减机器之后均衡

管理负载:根据实际机器的强弱来分配数据

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值