面试手写代码备份
从几十W的IP库中,判断某条IP是否存在
以IPV4举例,IPv4使用32位(4字节)地址,假设库中存的是点分十进制数据
方法
(1):将点分十进制数转化为long,排序后进行二分查找,如果只查一次的话,复杂度较大,查的次数多比较划算
(2):使用布隆过滤器,适合查不存在的数据,查存在的数据不一定准确,有误差,但是效率高
(3):将数据转化为二进制,建立一颗01二叉树,然后查找
public class IPUtil {
// 用于高位对应
public long ip2Long(String ipString) {
String[] ipSlices = ipString.split("\\.");
long rs = 0;
for (int i = 0; i < ipSlices.length; i++) {
long longSlice = Long.parseLong(ipSlices[i]) << (8 * i);
rs = rs | longSlice;
}
return rs;
}
// 用于压缩数据
public int ip2Int(String ipString) {
// 取 ip 的各段
String[] ipSlices = ipString.split("\\.");
int rs = 0;
for (int i = 0; i < ipSlices.length; i++) {
// 将 ip 的每一段解析为 int,并根据位置左移 8 位
int intSlice = Integer.parseInt(ipSlices[i]) << (8 * i);
// 或运算
rs = rs | intSlice;
}
return rs;
}
public String int2Ip(int ipInt) {
String[] ipString = new String[4];
for (int i = 0; i < 4; i++) {
// 每 8 位为一段,这里取当前要处理的最高位的位置
int pos = i * 8;
// 取当前处理的 ip 段的值
int and = ipInt & (255 << pos);
// 将当前 ip 段转换为 0 ~ 255 的数字,注意这里必须使用无符号右移
ipString[i] = String.valueOf(and >>> pos);
}
return String.join(".", ipString);
}
}
java手写Hashmap简易实现,实现get put resize功能
public class MyhashMap {
static class Node {
private Object key;
private Object value;
private Node next;
int hash;
Node(int hash, Object key, Object value, Node next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
}
Node[] table;
private int size = 8;
public int number = 0;
public MyhashMap() {
table = new Node[size];
}
public int getHash(int v, int length) {
return v & (length - 1);
}
private void resize() {
size *= size;
Node[] newTab = new Node[size];
for(int i=0; i<table.length; i++){
Node cur = table[i];
while(cur != null){
int newhash = getHash(cur.key.hashCode(), size);
Node newnode = newTab[newhash];
Node lastTemp = null;
if (newnode == null) {
newTab[newhash] = cur;
} else {
while (newnode != null) {
newnode = newnode.next;
}
lastTemp.next = cur;
}
cur = cur.next;
}
}
table = newTab;
}
public Object get(Object key) {
int hash = getHash(key.hashCode(), table.length);
Node temp = table[hash];
while (temp != null) {
if (key.equals(temp.key)) {
return temp.value;
} else
temp = temp.next;
}
return null;
}
public void put(Object key, Object value) {
if (number / size > 0.75) {
resize();
}
int hash = getHash(key.hashCode(), table.length);
Node node = new Node(hash, key, value, null);
Node temp = table[node.hash];
Node lastTemp = null;
boolean keyRepeat = false;
if (temp == null) {
table[node.hash] = node;
number++;
} else {
while (temp != null) {
if (temp.key.equals(key)) {
keyRepeat = true;
} else {
lastTemp = temp;
temp = temp.next;
}
}
if (!keyRepeat) {
lastTemp.next = node;
number++;
}
}
}
}
LRU
题目:https://leetcode-cn.com/problems/lru-cache/
class LRUCache {
class LinkedNode {
int key;
int value;
LinkedNode prev;
LinkedNode next;
}
HashMap<Integer, LinkedNode> cache = new HashMap<>();
int size;
int capacity;
LinkedNode head, tail;
public LRUCache(int capacity) {
this.size = 0;
this.capacity = capacity;
head = new LinkedNode();
tail = new LinkedNode();
head.next = tail;
tail.prev = head;
}
private void addNode(LinkedNode node) {
node.prev = head;
node.next = head.next;
head.next.prev = node;
head.next = node;
}
private void removeNode(LinkedNode node) {
LinkedNode prev = node.prev;
LinkedNode next = node.next;
prev.next = next;
next.prev = prev;
}
private void moveToHead(LinkedNode node) {
removeNode(node);
addNode(node);
}
private LinkedNode popTail() {
LinkedNode res = tail.prev;
removeNode(res);
return res;
}
public int get(int key) {
LinkedNode node = cache.get(key);
if (node == null)
return -1;
moveToHead(node);
return node.value;
}
public void put(int key, int value) {
LinkedNode node = cache.get(key);
if (node != null) {
node.value = value;
moveToHead(node);
} else {
LinkedNode newNode = new LinkedNode();
newNode.key = key;
newNode.value = value;
cache.put(key, newNode);
addNode(newNode);
size++;
if (size > capacity) {
LinkedNode tail = popTail();
cache.remove(tail.key);
size--;
}
}
}
}
双重锁单例模式
如果不使用volatile关键字,初始化instance时可能会发生重排序。
public class Singleton {
private volatile static Singleton instance;
public static Singleton getInstance(){
if(instance == null){
synchronized (Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
两个线程交替运行输出
(三个线程交替输出synchronized两遍)
Object lock = new Object();
Runnable run1 = new Runnable() {
public void run() {
synchronized (lock) {
for (int i = 1; i <= 20; i += 2) {
System.out.println(i);
try {
lock.notify();
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
Runnable run2 = new Runnable() {
public void run() {
synchronized (lock) {
for (int i = 2; i <= 20; i += 2) {
System.out.println(i);
try {
lock.notify();
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
Thread thread1 = new Thread(run1);
Thread thread2 = new Thread(run2);
thread1.start();
thread2.start();
使用Semaphore实现交替打印
public class SemaphoreTest {
private static Semaphore semaphore1=new Semaphore(1);
private static Semaphore semaphore2=new Semaphore(0);
public static void main(String[] args) {
new Thread(()->{
for (int i = 1; i <= 20; i += 2) {
try {
semaphore1.acquire();
System.out.println(i);
semaphore2.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(()->{
for (int i = 2; i <= 20; i += 2) {
try {
semaphore2.acquire();
System.out.println(i);
semaphore1.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
归并排序
public class ListSort {
class ListNode {
int val;
ListNode next;
ListNode(int val) {
this.val = val;
}
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
public ListNode sortList(ListNode head) {
if(head == null || head.next == null)
return head;
return mergeSort(head);
}
public ListNode mergeSort(ListNode head){
if(head.next == null)
return head;
ListNode fast = head, slow = head, temp = head;
while(fast != null && fast.next != null){
temp = slow;
fast = fast.next.next;
slow = slow.next;
}
temp.next = null;
ListNode a = mergeSort(head);
ListNode b = mergeSort(slow);
return merge(a, b);
}
public ListNode merge(ListNode a, ListNode b){
ListNode temphead = new ListNode(0);
ListNode cur = temphead;
while(a != null || b != null){
if(a == null){
cur.next = b;
cur = cur.next;
b = b.next;
}
else if(b == null){
cur.next = a;
cur = cur.next;
a = a.next;
}
else if(a. val < b.val){
cur.next = a;
cur = cur.next;
a = a.next;
}else{
cur.next = b;
cur = cur.next;
b = b.next;
}
}
return temphead.next;
}
}