常用算法(待完善...)

排序算法

归并排序

稳定

时间复杂度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,最近最少使用)

力扣 146. LRU 缓存

点击查看代码
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 (被淘汰)
    }
}
posted @ 2024-12-10 23:49  chendsome  阅读(24)  评论(0)    收藏  举报