zoukankan      html  css  js  c++  java
  • Data Structure and Algorithm

    • LRU Cache (least recently used)

      multi-level cache in CPU

      image-20210322081926011

      LRU: Hash Table + Double Linked List

      image-20210322082414832

      Time complexity: O(1) lookup, O(1) update/modify

      其他缓存替换方法

    • 146. LRU Cache

      Design a data structure that follows the constraints of a Least Recently Used (LRU) cache.

      Implement the LRUCache class:

      • LRUCache(int capacity) Initialize the LRU cache with positive size capacity.
      • int get(int key) Return the value of the key if the key exists, otherwise return -1.
      • void put(int key, int value) Update the value of the key if the key exists. Otherwise, add the key-value pair to the cache. If the number of keys exceeds the capacity from this operation, evict the least recently used key.

      Follow up:
      Could you do get and put in O(1) time complexity?

      Example 1:

      Input
      ["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
      [[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
      Output
      [null, null, null, 1, null, -1, null, -1, 3, 4]
      
      Explanation
      LRUCache lRUCache = new LRUCache(2);
      lRUCache.put(1, 1); // cache is {1=1}
      lRUCache.put(2, 2); // cache is {1=1, 2=2}
      lRUCache.get(1);    // return 1
      lRUCache.put(3, 3); // LRU key was 2, evicts key 2, cache is {1=1, 3=3}
      lRUCache.get(2);    // returns -1 (not found)
      lRUCache.put(4, 4); // LRU key was 1, evicts key 1, cache is {4=4, 3=3}
      lRUCache.get(1);    // return -1 (not found)
      lRUCache.get(3);    // return 3
      lRUCache.get(4);    // return 4
      

      Constraints:

      • 1 <= capacity <= 3000
      • 0 <= key <= 3000
      • 0 <= value <= 104
      • At most 3 * 104 calls will be made to get and put.
      class LRUCache {
          class DLinkedNode {
              int key;
              int value;
              DLinkedNode pre;
              DLinkedNode next;
              public DLinkedNode () {
                  
              }
              public DLinkedNode (int key, int value) {
                  this.key = key;
                  this.value = value;
              }
          }
          
          private Map<Integer, DLinkedNode> cache = new HashMap<>();
          private int size;
          private int cap;
          private DLinkedNode head, tail;
      
          public LRUCache(int capacity) {
              this.size = 0;
              this.cap = capacity;
              head = new DLinkedNode();
              tail = new DLinkedNode();
              head.next = tail;
              tail.pre = head;
          }
      
          public int get(int key) {
              DLinkedNode node = cache.get(key);
              if (node == null) {
                  return -1;
              }
              moveToHead(node);
              return node.value;
          }
      
          public void put(int key, int value) {
              DLinkedNode node = cache.get(key);
              if (node == null) {
                  DLinkedNode newNode = new DLinkedNode(key, value);
                  cache.put(key, newNode);
                  addToHead(newNode);
                  size++;
                  if (size > cap) {
                      DLinkedNode tail = removeTail();
                      cache.remove(tail.key);
                      size--;
                  }
              } else {
                  node.value = value;
                  moveToHead(node);
              }
          }
      
          private void moveToHead(DLinkedNode node) {
              removeNode(node);
              addToHead(node);
          }
      
          private void removeNode(DLinkedNode node) {
              node.pre.next = node.next;
              node.next.pre = node.pre;
          }
      
          private void addToHead(DLinkedNode node) {
              node.pre = head;
              node.next = head.next;
              head.next.pre = node;
              head.next = node;
          }
      
          private DLinkedNode removeTail() {
              DLinkedNode res = tail.pre;
              removeNode(res);
              return res;
          }
      }
      
    • Bloom Filter

      套在外层的缓存!

      一个很长的二进制向量和一系列随机映射函数。

      布隆过滤器可以用于检索一个元素是否在一个集合中。

      优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。

      image-20210322080759635

      只要有一个映射位是0,元素一定不存在;映射位都是1也不一定存在,存在误差。

      案例:

      1. 比特币网络
      2. 分布式系统(Map-Reduce) - Hadoop、search engine
      3. Redis缓存
      4. 垃圾邮件、评论等的过滤

      Java 实现:示例 1 示例 2

    • Sort

      image-20210322090858421

      image-20210322090927281

      重点:堆排序,快速排序,归并排序

      归并:先排序左右子数组,然后合并两个有序子数组
      快排:先调配出左右子数组,然后对于左右子数组进行排序

    • 1122. Relative Sort Array

      Given two arrays arr1 and arr2, the elements of arr2 are distinct, and all elements in arr2 are also in arr1.

      Sort the elements of arr1 such that the relative ordering of items in arr1 are the same as in arr2. Elements that don't appear in arr2 should be placed at the end of arr1 in ascending order.

      Example 1:

      Input: arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6]
      Output: [2,2,2,1,4,3,3,9,6,7,19]
      

      Constraints:

      • 1 <= arr1.length, arr2.length <= 1000
      • 0 <= arr1[i], arr2[i] <= 1000
      • All the elements of arr2 are distinct.
      • Each arr2[i] is in arr1.
      class Solution {
          public int[] relativeSortArray(int[] arr1, int[] arr2) {
              int i = 0;
              for (int i2 = 0; i2 < arr2.length; i2++) {
                  for (int i1 = 0; i1 < arr1.length; i1++) {
                      if (arr1[i1] == arr2[i2]) {
                          int t = arr1[i];
                          arr1[i++] = arr1[i1];
                          arr1[i1] = t;
                      }
                  }
              }
              Arrays.sort(arr1, i, arr1.length);
              return arr1;
          }
      }
      
    • 56. Merge Intervals

      Given an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.

      Example 1:

      Input: intervals = [[1,3],[2,6],[8,10],[15,18]]
      Output: [[1,6],[8,10],[15,18]]
      Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].
      

      Example 2:

      Input: intervals = [[1,4],[4,5]]
      Output: [[1,5]]
      Explanation: Intervals [1,4] and [4,5] are considered overlapping.
      

      Constraints:

      • 1 <= intervals.length <= 104
      • intervals[i].length == 2
      • 0 <= starti <= endi <= 104
      class Solution {
          public int[][] merge(int[][] intervals) {
              Deque<int[]> deque = new LinkedList<>();
              Arrays.sort(intervals, (x,y)->(x[1]-y[1]));
              Arrays.sort(intervals, (x,y)->(x[0]-y[0]));
              for (int[] interval : intervals) {
                  if (deque.isEmpty()) {
                      deque.addLast(interval);
                      continue;
                  }
                  int end = deque.peekLast()[1];
                  if (interval[0] <= end) {
                      deque.peekLast()[1] = Math.max(end, interval[1]);
                  } else {
                      deque.addLast(interval);
                  }
              }
              int n = deque.size();
              int[][] res = new int[n][2];
              for (int i = 0; i < n; i++) {
                  res[i] = deque.pollFirst();
              }
              return res;
          }
      }
      
    • 493. Reverse Pairs

      Given an array nums, we call (i, j) an *important reverse pair* if i < j and nums[i] > 2*nums[j].

      You need to return the number of important reverse pairs in the given array.

      Example1:

      Input: [1,3,2,3,1]
      Output: 2
      

      Example2:

      Input: [2,4,3,5,1]
      Output: 3
      

      Note:

      1. The length of the given array will not exceed 50,000.
      2. All the numbers in the input array are in the range of 32-bit integer.
      class Solution {
          int res = 0;
          public int reversePairs(int[] nums) {
              mergeSort(nums, 0, nums.length - 1);
              return res;
          }
      
          private void mergeSort(int[] nums, int left, int right) {
              if (right <= left) return ;
              int mid = (right - left) / 2 + left;
              mergeSort(nums, left, mid);
              mergeSort(nums, mid + 1, right);
              merge(nums, left, mid, right);
          }
      
          private void merge(int[] nums, int l1, int r1, int r2) {
              // count res
              int p = l1, q = r1 + 1;
              while (p <= r1 && q <= r2) {
                  if (nums[p] > (long) nums[q] * 2) {
                      res += r1 - p + 1;
                      q++;
                  } else p++;
              }
      
              int[] arr = new int[r2 - l1 + 1];
              int start = l1, i = 0, l2 = r1 + 1;
              while (l1 <= r1 && l2 <= r2) {
                  arr[i++] = nums[l1] > nums[l2] ? nums[l2++] : nums[l1++];
              }
              while (l1 <= r1) arr[i++] = nums[l1++];
              while (l2 <= r2) arr[i++] = nums[l2++];
              for (l1 = start; l1 <= r2; l1++) {
                  nums[l1] = arr[l1 - start];
              }
          }
      }
      
  • 相关阅读:
    稀疏矩阵解题数学库 -- UMFPACK
    国外程序猿整理的C++大全
    SQL实用语句大全
    this 三句话
    ELK 7.4.2 单机安装配置
    简单搭建DNS服务器——bind
    关于博客皮肤
    Golang 实现 array_push
    Golang 发送POST请求,加header头,带参数
    Golang 签名
  • 原文地址:https://www.cnblogs.com/peng8098/p/algorithm13.html
Copyright © 2011-2022 走看看