首页 > 算法 > 算法训练营第八周 位运算/布隆过滤器/LRU缓存/排序算法
2021
03-18

算法训练营第八周 位运算/布隆过滤器/LRU缓存/排序算法

第八周学习笔记

一、位运算

运算符及含义

运算符 含义
<< 左移
>> 右移
>>> 无符号右移
& 按位与
| 按位或
~ 按位取反
^ 按位异或

位运算要点

•判断奇偶  x % 2 == 1 ——> (x & 1) == 1    
                 
x % 2 == 0 ——> (x & 1) == 0    
•除以2   x >> 1 ——> x / 2.    
  即: x = x / 2; ——> x = x >> 1    
  mid = (left + right) / 2; ——> mid = (left + right) >> 1    
•X = X & (X - 1)   清零最低位的 1     
•X & (-X)    得到最低位的 1    
•X & ~X => 0    

二、LRU Cache

最近最少使用的被替换
查询 O(1), 修改O(1)

Java实现

class LRUCache {

    class DLinkedNode {
        int key;
        int value;
        DLinkedNode pre;
        DLinkedNode next;
    }

    /**
     * Always add the new node right after head;
     */
    private void addNode(DLinkedNode node) {

        node.pre = head;
        node.next = head.next;

        head.next.pre = node;
        head.next = node;
    }

    /**
     * Remove an existing node from the linked list.
     */
    private void removeNode(DLinkedNode node) {
        DLinkedNode pre = node.pre;
        DLinkedNode post = node.next;

        pre.next = post;
        post.pre = pre;
    }

    /**
     * Move certain node in between to the head.
     */
    private void moveToHead(DLinkedNode node) {
        this.removeNode(node);
        this.addNode(node);
    }

    // pop the current tail.
    private DLinkedNode popTail() {
        DLinkedNode res = tail.pre;
        this.removeNode(res);
        return res;
    }

    private HashMap<Integer, DLinkedNode> cache;
    private int len;
    private int cap;
    private DLinkedNode head, tail;

    public LRUCache(int capacity) {
        cache = new HashMap<Integer, DLinkedNode>();
        this.len = 0;
        this.cap = capacity;

        head = new DLinkedNode();
        head.pre = null;

        tail = new DLinkedNode();
        tail.next = null;

        head.next = tail;
        tail.pre = head;
    }

    public int get(int key) {

        DLinkedNode node = cache.get(key);
        if (node == null) {
            return -1; // should raise exception here.
        }

        // move the accessed node to the head;
        this.moveToHead(node);

        return node.value;
    }


    public void put(int key, int value) {
        DLinkedNode node = cache.get(key);

        if (node == null) {

            DLinkedNode newNode = new DLinkedNode();
            newNode.key = key;
            newNode.value = value;

            this.cache.put(key, newNode);
            this.addNode(newNode);

            ++len;

            if (len > cap) {
                // pop the tail
                DLinkedNode tail = this.popTail();
                this.cache.remove(tail.key);
                --len;
            }
        } else {
            // update the value.
            node.value = value;
            this.moveToHead(node);
        }
    }
}

三、布隆过滤器

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

四、排序算法

排序算法可分为基于比较的排序算法和非基于比较的排序算法。
基于比较的排序算法有:选择排序,冒泡排序,插入排序,希尔排序,堆排序,快速排序,归并排序。
非比较类排序有:计数排序,计数排序,桶排序。

各算法的时间和空间复杂度

算法训练营第八周 位运算/布隆过滤器/LRU缓存/排序算法 - 第1张  | Weiguang的博客

1.冒泡排序

  public static void bubbleSort(int[] arr) {
    if (arr == null || arr.length < 2) {
      return;
    }
    for (int i = 0; i < arr.length - 1; i++) {
      for (int j = 1; j < arr.length - i; j++) {
        if (arr[j] < arr[j - 1]) {
          int temp = arr[j];
          arr[j] = arr[j - 1];
          arr[j - 1] = temp;
        }
      }
    }
  }

2.选择排序

  public static void selectionSort(int[] arr) {
    if (arr == null || arr.length < 2) {
      return;
    }
    for (int i = 0; i < arr.length - 1; i++) {
      for (int j = i + 1; j < arr.length; j++) {
        if (arr[j] < arr[i]) {
          int temp = arr[i];
          arr[i] = arr[j];
          arr[j] = temp;
        }
      }
    }
  }

### 3.插入排序

  public static void insertionSort(int[] arr) {
    if (arr == null || arr.length < 2) {
      return;
    }
    for (int i = 1; i < arr.length; i++) {
      for (int j = i; j > 0; j--) {
        if (arr[j] < arr[j - 1]) {
          int temp = arr[j];
          arr[j] = arr[j - 1];
          arr[j - 1] = temp;
        } else {
          break;
        }
      }
    }
  }

### 4.希尔排序

  public static void hillSort(int[] arr) {
    if (arr == null || arr.length < 2) {
      return;
    }
    for (int gap = arr.length / 2; gap > 0; gap /= 2) {
      for (int i = gap; i < arr.length; i++) {
        int j = i;
        while (j - gap >= 0 && arr[j] < arr[j - gap]) {
          int temp = arr[j];
          arr[j] = arr[j - gap];
          arr[j - gap] = temp;
          j -= gap;
        }
      }
    }
  }

### 5.堆排序

  public static void heapSort(int[] arr) {
    if (arr == null || arr.length < 2) {
      return;
    }
    PriorityQueue<Integer> pq = new PriorityQueue<>();
    for (int i : arr) {
      pq.offer(i);
    }
    for (int i = 0; i < arr.length; i++) {
      arr[i] = pq.poll();
    }
  }

### 6.快速排序

  public static void quickSort(int[] arr) {
    if (arr == null || arr.length < 2) {
      return;
    }
    quickSort(arr, 0, arr.length - 1);
  }

  public static void quickSort(int[] arr, int begin, int end) {
    if (begin >= end) {
      return;
    }
    int pivot = partition(arr, begin, end);
    quickSort(arr, 0, pivot - 1);
    quickSort(arr, pivot + 1, end);
  }

  public static int partition(int[] arr, int begin, int end) {
    int pivot = end, counter = begin;
    for (int i = begin; i < end; i++) {
      if (arr[i] < arr[pivot]) {
        int temp = arr[i];
        arr[i] = arr[counter];
        arr[counter] = temp;
        counter++;
      }
    }
    int temp = arr[pivot];
    arr[pivot] = arr[counter];
    arr[counter] = temp;
    return counter;
  }

### 7.二路归并排序

  public static void mergeSort(int[] arr, int begin, int end) {
    if (begin >= end) {
      return;
    }
    int mid = begin + ((end - begin) >> 1);
    mergeSort(arr, begin, mid);
    mergeSort(arr, mid + 1, end);
    merge(arr, begin, end, mid);
  }

  private static void merge(int[] arr, int begin, int end, int mid) {
    int[] temp = new int[end - begin + 1];
    int i = begin, j = mid + 1, k = 0;
    while (i <= mid && j <= end) {
      temp[k++] = arr[i] < arr[j] ? arr[i++] : arr[j++];
    }
    while (i <= mid) {
      temp[k++] = arr[i++];
    }
    while (j <= end) {
      temp[k++] = arr[j++];
    }
    for (int p = 0; p < temp.length; p++) {
      arr[begin + p] = temp[p];
    }
  }

### 8.计数排序

当max很大时,计数排序无法使用

  public static void countingSort(int[] arr, int max) {
    if (arr == null || arr.length < 2) {
      return;
    }
    int[] count = new int[max + 1];
    for (int i = 0; i < arr.length; i++) {
      count[arr[i]]++;
    }
    int k = 0;
    for (int i = 0; i <= max; i++) {
      while (count[i]-- > 0) {
        arr[k++] = i;
      }
    }
  }
最后编辑:
作者:lwg0452
这个作者貌似有点懒,什么都没有留下。
捐 赠如果您觉得这篇文章有用处,请支持作者!鼓励作者写出更好更多的文章!

留下一个回复

你的email不会被公开。