程序员代码面试指南补充

目录

 

1 hash函数的性质

(1)输入域是无穷的,但是输出域是有限的

(2)不是随机产生的输出,相同的输入一定对应相同的输出

(3)不同的输入可能会导致相同的输出(hash碰撞)

(4)输出的值在整个输出域几乎是均匀分布的(离散性)

2 hash表

hash表的存储数据如下图所示:

 每个字符是随机均匀分布在长度为10的数组上的,因为字符多,那么在相同位置字符使用链表连接的(JDK1.8之前,从1.8之后用红黑树连接)

Java中有hashMap和hashSet这两个其实从结构上来说是一样的,可以认为value只不过是key的伴随数据而已,也就是封装的对象不同,但是基本的存储结构还是一样的。

3 布隆过滤器

 

 

 

 总结:布隆过滤器的提示点:

1、黑名单问题;2、要求内存空间极为苛刻;3、单样本的大小可能很大;4、允许有失误率(可能要自己问)

4 一致性hash

最初hash用来解决服务器负载均衡问题的场景:

上图中保证了服务其存储的信息是基本均匀分布的,但是这样有一个问题,当我需要加增加一个服务器或者减少一个服务器时那么就需要重新对所有的信息取模,这样做成本太大了,因此上面的方法只适合服务器台数固定的场景使用。

为了解决上述问题提出了环形结构,按照顺时针方向把数据存储到相应的服务器中。考虑当新来一个服务器m4时,只需要把原本在m3中存储的m2~m4这段数据存储在m4中,这样只是修改了m3服务器上的部分数据,所花费的代价很少。

在底层实现时,是利用数组来实现环形结构,将服务器得到的hash值进行排序,得到一个有序数组,那么新来m4时,只需要二分查找比其大的最近的服务器hash值即可。

上面的方法解决了服务器数量变化的问题的,但是出现了另外两个问题:

(1)当服务器数目过少时,因为hash函数本身的性质很有可能造成某几个服务器得到hash值距离太近,这样就会导致负载不均衡问题。

(2)就算第一步问题解决了,当新增加一个服务器是,还会造成负载不均衡问题。

 为了解决上面的新的分布不均的问题,提出了虚拟节点技术:三个服务器各自分配1万个虚拟节点,将虚拟节点计算出的hash值对应在环上,这样数目足够大就可以均匀分布了。

 当新增一个服务器时,同样设置1万个虚拟节点,还是按照上面的顺时针迁移数据的方法,这时m1、m2、m3只需要各自移动1/12的数据即可,这样的性能还是可以接受的。

虚拟节点具体实现:

一个服务器上的对应着多个ip地址,选择其中的一万个,分别计算出hash值,将这些hash值对应在环上,即为虚拟节点

5 哈夫曼(霍夫曼)编码问题 

Huffman Tree:给定n个权值作为n个叶子结点,构造一颗二叉树,若树的带权路径长度达到最小,则这棵树被称为哈夫曼树(也就是非叶子节点的权值和最小)。

具体应用:

一块金条切成两半,是需要花费和长度数值一样的铜板的。比如长度为20的金条,不管切成长度多大的两半,都要花费20个铜板。一群人想整分整块金条,怎么分最省铜板? 

例如,给定数组{10,20,30},代表一共三个人,整块金条长度为10+20+30=60.金条要分成10,20,30三个部分。如果,先把长度60的金条分成10和50,花费60再把长度50的金条分成20和30,花费50一共花费110铜板。但是如果,先把长度60的金条分成30和30,花费60再把长度30金条分成10和20,花费30一共花费90铜板。输入一个数组,返回分割的最小代价。

可以借用最小堆实现:

 

public static int lessMoney(int[] arr){
    PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
    //将数组中所有的元素放入最小堆中
    for (int i = 0; i < arr.length; i++) {
        priorityQueue.add(arr[i]);
    }
    //所需要花费的金钱
    int sum = 0;
    //存储堆顶元素之和
    int cur = 0;
    while (priorityQueue.size() > 1){
        cur = priorityQueue.poll()+priorityQueue.poll();
        sum+= cur;
        priorityQueue.add(cur);
    }
    return sum;
}

6 贪心堆

输入:参数1,正数数组costs;参数2,正数数组profits;参数3,正数k;参数4,正数m

costs[i]表示i号项目的花费;profits[i]表示i号项目在扣除花费之后还能挣到的钱(利润);k表示你不能并行、只能串行的最多做k个项目;m表示你初始的资金

说明:你每做完一个项目,马上获得的收益,可以支持你去做下一个项目。

输出:你最后获得的最大钱数

以下图为例,一开始初始资金为5,只能在花费为1和4中选择收益最大,当进行完第一轮后资金为11,然后在花费小于11中选择剩下的最大的。

 

在这道题目中可以用一个最小堆和最大堆来解决问题,在最小堆中按照花费排序,弹出小于启动资金的

 

 这个代码好像没找到

 

 

 

 

 

 

0

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值