Java面试13|算法
1、冒泡排序
for(int i=0;i<n;i++){ for(int j=0;j<n-1-i;j++){ if(temp[j]>temp[j+1]){ int t=temp[j]; temp[j]=temp[j+1]; temp[j+1]=t; } } }
2、快速排序
public void quicksort(int[] array,int left,int right){ if(left<right){ int key = array[left]; int low = left; int high = right; while(low<high){ while(low<high && array[high]>=key){ high--; } array[low] = array[high]; while(low<high && array[low]<=key){ low++; } array[high] = array[low]; } array[low] = key; quicksort(array,left,low-1); quicksort(array,low+1,right); } }
3、一致性hash
一致性hash算法可以解决容错性和扩展性的问题。
系统中增加更多的虚拟节点,可以更好的解负载均衡问题。
public class Shard<S> { // S类封装了机器节点的信息 ,如name、password、ip、port等 private TreeMap<Long, S> circle; // 将整个hash值空间组成一个虚拟的环 private List<S> shards; // 真实机器节点 private final int NODE_NUM = 100; // 每个机器节点关联的虚拟节点个数 private final HashFunction hashFunction; // 选择一个碰撞率低的hash()函数 public Shard(List<S> shards,HashFunction hashFunction) { super(); this.shards = shards; this.hashFunction = hashFunction; init(); } private void init() { // 初始化一致性hash环 circle = new TreeMap<Long, S>(); for (int i = 0; i<shards.size(); ++i) { // 每个真实机器节点都需要关联虚拟节点 final S shardInfo = shards.get(i); add(shardInfo); } } public void add(S node) { for (int i = 0; i < NODE_NUM; i++) { // 虚拟节点用一些特定的hash值来替代,这样形成了hash值到真实节点的映射 circle.put(hashFunction.hash(node.toString() + i), node); } } public void remove(S node) { for (int i = 0; i < NODE_NUM; i++) { // 移除真实节点下对应的所有虚拟节点(特定的一些hash值) circle.remove(hashFunction.hash(node.toString() + i)); } } public S getShardInfo(String key) { // SortedMap<Long, S> tail = circle.tailMap(hash(key)); // 沿环的顺时针找到一个虚拟节点 // if (tail.size() == 0) { // return circle.get(circle.firstKey()); // } // return tail.get(tail.firstKey()); // 返回该虚拟节点对应的真实机器节点的信息 if (circle.isEmpty()) { return null; } Long hash = hashFunction.hash(key); // 如果当前hash值没有定位到虚拟节点 if (!circle.containsKey(hash)) { SortedMap<Long, S> tailMap = circle.tailMap(hash); hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey(); } return circle.get(hash); } }
class Machine { String ip; String name; public Machine(String ip, String name) { this.ip = ip; this.name = name; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getName() { return name; } public void setName(String name) { this.name = name; } } public class Test { public static void main(String[] args) { Machine a = new Machine("192.168.0.1", "a"); Machine b = new Machine("192.168.0.2", "b"); Machine c = new Machine("192.168.0.3", "c"); List<Machine> list = Arrays.asList(a, b, c); Map<String, Integer> map = new HashMap<String, Integer>(); Shard<Machine> mcs = new Shard<Machine>(list, new HashFunction()); // 存储0到2000个数,看存储在各个机器上的数的数量是否大致均匀 for (int i = 0; i < 2000; i++) { String key = i + ""; Machine m = mcs.getShardInfo(key); if (map.get(m.getIp()) == null) { map.put(m.getIp(), 0); } else { map.put(m.getIp(), (int) map.get(m.getIp()) + 1); } } Iterator<Entry<String, Integer>> iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Entry<String, Integer> entry = iterator.next(); System.out.println(entry.getKey() + "/" + entry.getValue()); } } }
某次运行后的结果如下:
192.168.0.2/599 192.168.0.1/698 192.168.0.3/700
4、LRU最近最少使用算法
要效率的话使用hash搜索,要实现最近最少的话就用双向链表
public class LRUCache { private int cacheSize; private HashMap<Object, Entry> nodes; // 缓存容器 ,为了提高查询速度需要这个结构 private int currentSize; private Entry first; // 链表头 private Entry last; // 链表尾 static class Entry { Entry prev; Entry next; Object key; Object value; } public LRUCache(int i) { currentSize = 0; cacheSize = i; nodes = new HashMap<Object, Entry>(i); } /** * 获取缓存中对象,并把它放在最前面 */ public Entry get(Object key) { Entry node = nodes.get(key); if (node != null) { moveToHead(node); return node; } else { return null; } } /** * 添加 entry到hashtable, 并把entry */ public void put(Object key, Object value) { //先查看hashtable是否存在该entry, 如果存在,则只更新其value Entry node = nodes.get(key); if (node == null) { //缓存容器是否已经超过大小. if (currentSize >= cacheSize) { nodes.remove(last.key); removeLast(); } else { currentSize++; } node = new Entry(); } node.value = value; //将最新使用的节点放到链表头,表示最新使用的. moveToHead(node); nodes.put(key, node); } /** * 将entry删除, 注意:删除操作只有在cache满了才会被执行 */ public void remove(Object key) { Entry node = nodes.get(key); //在链表中删除 if (node != null) { if (node.prev != null) { node.prev.next = node.next; } if (node.next != null) { node.next.prev = node.prev; } if (last == node) last = node.prev; if (first == node) first = node.next; } //在hashtable中删除 nodes.remove(key); } /** * 删除链表尾部节点,即使用最后 使用的entry */ private void removeLast() { //链表尾不为空,则将链表尾指向null. 删除连表尾(删除最少使用的缓存对象) if (last != null) { if (last.prev != null){ last.prev.next = null; } else{ first = null; } last = last.prev; } } /** * 移动到链表头,表示这个节点是最新使用过的 */ private void moveToHead(Entry node) { if (node == first) return; if (node.prev != null) node.prev.next = node.next; if (node.next != null) node.next.prev = node.prev; if (last == node) last = node.prev; if (first != null) { node.next = first; first.prev = node; } first = node; node.prev = null; if (last == null){ last = first; } } /* * 清空缓存 */ public void clear() { first = null; last = null; currentSize = 0; } }
Java面试13|算法的更多相关文章
- Java面试常见算法题
1.实现字符串反转 提供七种方案实现字符串反转 import java.util.Stack; public class StringReverse { public static String re ...
- 【java面试】算法篇之堆排序
一.堆的概念 堆是一棵顺序存储的完全二叉树.完全二叉树中所有非终端节点的值均不大于(或不小于)其左.右孩子节点的值. 其中每个节点的值小于等于其左.右孩子的值,这样的堆称为小根堆: 其中每个节点的值大 ...
- 【java面试】算法篇
1.冒泡排序 /** * 冒泡排序 * 比较相邻的元素.如果第一个比第二个大,就交换他们两个. * 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. ...
- Java面试系列
如果你的面试简历是如下这样写的,请务必准备回答下面的所有问题. 面试职位:Java高级工程师 专业技能: (1)牢固掌握Java基础知识,如集合.并发.I/O等,并对Java源码有一定的研究. (2) ...
- 分享13道上海尚学堂拿回来的Java面试真题,这些都是Java核心常见问题,想拿OFFER必看!
上海尚学堂Java培训学员参加面试带回来的真题,分享出来与大家,希望大家能认真地看看做一遍.后面有详细题解答案,对照下,看看自己做得怎么样,把这些面试遇到的真题全部掌握,做好面试笔试前的准备. 一.1 ...
- 编程之法:面试和算法心得(字符串包含java实现)
内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 给定两个分别由字母组成的字符串A和字符串B,字符串B的长度比字符串A短.请问,如何最快地判断字符串B中所有字母是否都 ...
- [转载]java面试中经常会被问到的一些算法的问题
Java面试中经常会被问到的一些算法的问题,而大部分算法的理论及思想,我们曾经都能倒背如流,并且也能用开发语言来实现过, 可是很多由于可能在项目开发中应用的比较少,久而久之就很容易被忘记了,在此我分享 ...
- 编程之法:面试和算法心得(旋转字符串java实现)
内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 给定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部,如把字符串“abcdef”前面的2个字符'a'和'b ...
- java面试一日一题:java中垃圾回收算法有哪些
问题:请讲下在java中有哪些垃圾回收算法 分析:该问题主要考察对java中垃圾回收的算法以及使用场景 回答要点: 主要从以下几点去考虑, 1.GC回收算法有哪些 2.每种算法的使用场景 3.基于垃圾 ...
随机推荐
- --@angularJS--指令与控制器之间的交互demo
1.index.html: <!DOCTYPE HTML><html ng-app="app"><head> <title>c ...
- Recurrent Neural Network系列3--理解RNN的BPTT算法和梯度消失
作者:zhbzz2007 出处:http://www.cnblogs.com/zhbzz2007 欢迎转载,也请保留这段声明.谢谢! 这是RNN教程的第三部分. 在前面的教程中,我们从头实现了一个循环 ...
- 使用php实现网站验证码功能【博主推荐】
验证码是网站常用的一项安全措施,也是新人站长较难掌握的一项技能,这里我向大家介绍一简单有效的验证码实现方法. 开始之前 在正式开始之前我们需要打开php的gd2图形库支持(在php. ...
- TPS及计算方法
个事务,TPS为6 / 60s = 0.10 TPS.同时我们会知道事务的响应时间(或节拍),以此例,60秒完成6个事务也同时代表每个事务的响应时间或节拍为10秒. 利特尔法则 (Little' ...
- js小功能合集:计算指定时间距今多久、评论树核心代码、字符串替换和去除。
1.计算指定时间距今多久 var date1=new Date('2017/02/08 17:00'); //开始时间 var date2=new Date(); //当前时间 var date3=d ...
- 面向UI编程:ui.js 1.1 使用观察者模式完成组件之间数据流转,彻底分离组件之间的耦合,完成组件的高内聚
开头想明确一些概念,因为有些概念不明确会导致很多问题,比如你写这个框架为什么不去解决啥啥啥的问题,哎,心累. 什么是框架? 百度的解释:框架(Framework)是整个或部分系统的可重用设计,表现为一 ...
- SharePoint 2016 文档库的新功能简介
今天,重装了一下SharePoint 2016,想多了解了解,看到一些自己平时没注意的功能,或者新的功能,分享一下给大家. 1.界面上操作的变换,多了一排按钮,更像SharePoint Online了 ...
- Java获取http和https协议返回的json数据
现在很多公司都是将数据返回一个json,而且很多第三方接口都是返回json数据,而且还需要使用到http协议,http协议是属于为加密的协议,而https协议需要SSL证书,https是将用户返回的信 ...
- LAMP学习小记
记录今天学习到的解决LAMP环境搭建的两个小问题: 问题1.xshell无法连接到虚拟机上的linux主机 解决方法: (1)进入网络配置文件: vi /etc/sysconfig/network-s ...
- Input file 文本框美化
HTML原生的input file 上传按钮有多(无)不(力)漂(吐)亮(槽)我就不多说了.大家几乎在项目中都会有遇到图片.等文件需要上传的地方,好看的文件上传按钮会使人身心愉悦(我瞎说的).好了不多 ...