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.基于垃圾 ...
随机推荐
- android的引用库类
在eclipse中的项目里,有时需要外来的jar文件.添加后就可以消去程序中的红条条啦~~~~~~~~~可以照下面的说明添加. 方法/步骤 打开eclipse,导入项目 右击 项目 , “Bu ...
- SSH系统介绍
SSH的系统中,对象的调用流程是:JSP->Action->Service->DAO->Hibernate,数据的流向是ActionFormBean接受用户的数据,Action ...
- spring mvc 入门示例
classpath <?xml version="1.0" encoding="UTF-8"?> <classpath> <cla ...
- Flex 开发框架汇总
1.现有成熟Flex框架 Cairngorm (Adobe Open Source) - MVC framework PureMVC (Open Source) - MVC framework ...
- Bootstrap入门(二十九)JS插件6:弹出框
Bootstrap入门(二十九)JS插件6:弹出框 加入小覆盖的内容,像在iPad上,用于存放非主要信息 弹出框是依赖于工具提示插件的,那它也和工具提示是一样的,是需要初始化才能够使用的 首先我们引入 ...
- 一篇完整的FlexBox布局指南
一篇完整的FlexBox布局指南 转载请标注本文链接并附带以下信息: 译:Cydiacen 作者:CHRIS COYIER 原文:A Complete Guide to Flexbox 原文更新于 2 ...
- javascript 计算两个日期的差值
代码 Typescript版 /** * TimeSpan just like the class TimpSpan in C# ,represent the time difference * @c ...
- 前端开发在IOS端遇到的一个诡异问题(Delegate 失效)
一.前言 最近同事问到一个问题,一个前端页面在IOS端真机测试下出现一个比较诡异的问题,如果没有遇到过估计也是一筹莫展.今天特此记录一下,或许能帮到后面遇到这个问题的朋友少绕一些弯路.这是关于JQue ...
- Vuex核心知识(2.0)
Vuex 是一个专门为 Vue.js 应该程序开发的状态管理模式,它类似于 Redux 应用于 React 项目中,他们都是一种 Flux 架构.相比 Redux,Vuex 更简洁,学习成本更低.希望 ...
- Struts2系列笔记(4)---Ation类访问servlet
Ation类访问servlet Ation类有三种方式servlet: (1)间接的方式访问Servlet API ---使用ActionContext对象 (2) 实现接口,访问Action时完 ...