常用算法(待完善...)
排序算法
归并排序
稳定
时间复杂度O nlogn
空间复杂度O n
点击查看代码
class Solution {
public int[] sortArray(int[] nums) {
mergeSort(nums, 0, nums.length -1);
return nums;
}
private void mergeSort(int nums[], int left, int right){
if(left>=right){
return;
}
int mid = (left + right) >>> 1;
mergeSort(nums, left, mid);
mergeSort(nums, mid+1, right);
mergeArr(nums,left, mid, mid+1, right);
}
private void mergeArr(int[] nums, int l1, int r1, int l2, int r2){
int[] temp = new int[r2 - l1 + 1];
int i = l1;
int j = l2;
int k = 0;
while(i <= r1 && j <= r2){
if(nums[i] <= nums[j]){
temp[k++] = nums[i++];
}else{
temp[k++] = nums[j++];
}
}
while(i <= r1){
temp[k++] = nums[i++];
}
while(j <= r2){
temp[k++] = nums[j++];
}
System.arraycopy(temp, 0, nums, l1, temp.length);
}
}
快速排序
不稳定
时间复杂度O nlogn, 排好了,或者逆序的时候 退化成 O n^2
空间复杂度O logn
点击查看代码
class Solution {
public int[] sortArray(int[] nums) {
QuickSort(nums, 0, nums.length-1);
return nums;
}
private void QuickSort(int[] nums, int left, int right){
if(left >= right){
return;
}
int pivotIdx = partition(nums, left, right);
QuickSort(nums,left,pivotIdx - 1);
QuickSort(nums, pivotIdx + 1, right);
}
private int partition(int[] nums, int left , int right){
// 基准点放最左边
int pivot = nums[left];
// j左边都是比基准点小的数
int j = left;
for(int i = left+1; i <= right; i++){
if(nums[i] <= pivot){
j++;
swap(nums, i, j);
}
}
// 交互基准点,基准点的位置就是j了
swap(nums, left, j);
return j;
}
private void swap(int[] nums, int i , int j){
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
}
内存淘汰算法
LRU(Least Recently Used,最近最少使用)
点击查看代码
class LRUCache {
static class Node{
int key, val;
Node pre, next;
Node(int k, int v){
key = k;
val = v;
}
}
Map<Integer, Node> map;
Node dummy;
int capacity;
public LRUCache(int capacity) {
this.capacity = capacity;
map = new HashMap<>();
dummy = new Node(0, 0);
dummy.next = dummy;
dummy.pre = dummy;
}
public int get(int key) {
// 查
Node node = getNode(key);
if(node == null) {
return -1;
}
return node.val;
}
public void put(int key, int value) {
Node node = getNode(key);
if(node!=null){
node.val = value;
return;
}
node = new Node(key, value);
map.put(key, node);
pushLast(node);
if(map.size() > capacity){
Node head = dummy.next;
map.remove(head.key);
remove(head);
}
}
private Node getNode(int key){
if(!map.containsKey(key)){
return null;
}
// 存在
Node node = map.get(key);
remove(node);
pushLast(node);
return node;
}
private void remove(Node node){
node.pre.next = node.next;
node.next.pre = node.pre;
}
private void pushLast(Node node){
Node tail = dummy.pre;
tail.next = node;
node.pre = tail;
dummy.pre = node;
node.next = dummy;
}
}
带过期时间的LRU
点击查看代码
public class ExpirableLRUCache {
// 内部类,实现双向链表。链表队首约定为最近使用的元素
private static class Node {
int key, value;
long expireTime; // 过期时间
Node prev, next;
Node(int k, int v, long expireTime) {
key = k;
value = v;
this.expireTime = expireTime;
}
}
private final int capacity;
private final long expireAfterWrite; // 过期时间,单位毫秒
private final Node dummy = new Node(0, 0, 0); // 哨兵节点
private final Map<Integer, Node> keyToNode = new HashMap<>();
public ExpirableLRUCache(int capacity, long expireAfterWrite) {
this.capacity = capacity;
this.expireAfterWrite = expireAfterWrite;
dummy.next = dummy;
dummy.prev = dummy;
}
// 获取元素
public int get(int key) {
// 1. 判断元素是否存在,并检查是否过期
Node node = getNode(key);
// 2. 存在且未过期,返回对应元素
if (node != null) {
return node.value;
}
// 3. 不存在或已过期,返回-1
return -1;
}
// 放入元素
public void put(int key, int value) {
long now = System.currentTimeMillis();
// 1. 判断元素是否存在,并检查是否过期
Node node = getNode(key);
// 2. 存在且未过期,更新值
if (node != null) {
node.value = value;
node.expireTime = now + expireAfterWrite; // 更新过期时间
return;
}
// 3. 不存在或已过期,在链表首部增加元素,并将key加入map中
node = new Node(key, value, now + expireAfterWrite);
pushFront(node);
keyToNode.put(key, node);
// 4. 是否超出容量限制
if (keyToNode.size() > capacity) {
// 4.1. 超出限制,需要淘汰队尾(最近最少使用)
Node backNode = dummy.prev;
keyToNode.remove(backNode.key);
remove(backNode);
}
}
// 获取对应key上的元素,如果过期则返回null
private Node getNode(int key) {
// 1. 哈希表中没有key,返回null
if (!keyToNode.containsKey(key)) {
return null;
}
// 2. 找到对应元素
Node node = keyToNode.get(key);
// 3. 检查是否过期
if (System.currentTimeMillis() > node.expireTime) {
// 3.1. 过期,移除该节点
remove(node);
keyToNode.remove(key);
return null;
}
// 4. 未过期,更新使用状态
remove(node);
pushFront(node);
return node;
}
// 从链表中移除节点
private void remove(Node node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
// 将节点添加到链表首部
private void pushFront(Node node) {
node.prev = dummy;
node.next = dummy.next;
dummy.next.prev = node;
dummy.next = node;
}
public static void main(String[] args) throws InterruptedException {
ExpirableLRUCache cache = new ExpirableLRUCache(3, 1000); // 容量为3,过期时间为1秒
cache.put(1, 1);
System.out.println(cache.get(1)); // 输出: 1
Thread.sleep(1500); // 等待1.5秒,让key1过期
cache.put(2, 2);
cache.put(3, 3);
System.out.println(cache.get(1)); // 输出: -1 (已过期)
System.out.println(cache.get(2)); // 输出: 2
cache.put(4, 4);
cache.put(5, 5); // 添加新条目,触发LRU淘汰
System.out.println(cache.get(3)); // 输出: -1 (被淘汰)
}
}
本文来自博客园,作者:chendsome,转载请注明原文链接:https://www.cnblogs.com/chendsome/p/18598374

浙公网安备 33010602011771号