class035 数据结构设计高频题【算法】

简介: class035 数据结构设计高频题【算法】

class035 数据结构设计高频题【算法】

算法讲解035【必备】数据结构设计高频题

code1 设计有setAll功能的哈希表

// setAll功能的哈希表

// 测试链接 : https://www.nowcoder.com/practice/7c4559f138e74ceb9ba57d76fd169967

// 请同学们务必参考如下代码中关于输入、输出的处理

// 这是输入输出处理效率很高的写法

// 提交以下的code,提交时请把类名改成"Main",可以直接通过

思路:带时间戳

package class035;
// setAll功能的哈希表
// 测试链接 : https://www.nowcoder.com/practice/7c4559f138e74ceb9ba57d76fd169967
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
// 提交以下的code,提交时请把类名改成"Main",可以直接通过
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.HashMap;
public class Code01_SetAllHashMap {
  public static HashMap<Integer, int[]> map = new HashMap<>();
  public static int setAllValue;
  public static int setAllTime;
  public static int cnt;
  public static void put(int k, int v) {
    if (map.containsKey(k)) {
      int[] value = map.get(k);
      value[0] = v;
      value[1] = cnt++;
    } else {
      map.put(k, new int[] { v, cnt++ });
    }
  }
  public static void setAll(int v) {
    setAllValue = v;
    setAllTime = cnt++;
  }
  public static int get(int k) {
    if (!map.containsKey(k)) {
      return -1;
    }
    int[] value = map.get(k);
    if (value[1] > setAllTime) {
      return value[0];
    } else {
      return setAllValue;
    }
  }
  public static int n, op, a, b;
  public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    StreamTokenizer in = new StreamTokenizer(br);
    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
    while (in.nextToken() != StreamTokenizer.TT_EOF) {
      map.clear();
      setAllValue = 0;
      setAllTime = -1;
      cnt = 0;
      n = (int) in.nval;
      for (int i = 0; i < n; i++) {
        in.nextToken();
        op = (int) in.nval;
        if (op == 1) {
          in.nextToken();
          a = (int) in.nval;
          in.nextToken();
          b = (int) in.nval;
          put(a, b);
        } else if (op == 2) {
          in.nextToken();
          a = (int) in.nval;
          out.println(get(a));
        } else {
          in.nextToken();
          a = (int) in.nval;
          setAll(a);
        }
      }
    }
    out.flush();
    out.close();
    br.close();
  }
}

code2 146. LRU 缓存

// 实现LRU结构

// 测试链接 : https://leetcode.cn/problems/lru-cache/

思路:HashMap+双向链表(新增结点到尾部,删除头部的结点,将结点移到尾部)

package class035;
import java.util.HashMap;
// 实现LRU结构
public class Code02_LRU {
  // 测试链接 : https://leetcode.cn/problems/lru-cache/
  class LRUCache {
    class DoubleNode {
      public int key;
      public int val;
      public DoubleNode last;
      public DoubleNode next;
      public DoubleNode(int k, int v) {
        key = k;
        val = v;
      }
    }
    class DoubleList {
      private DoubleNode head;
      private DoubleNode tail;
      public DoubleList() {
        head = null;
        tail = null;
      }
      public void addNode(DoubleNode newNode) {
        if (newNode == null) {
          return;
        }
        if (head == null) {
          head = newNode;
          tail = newNode;
        } else {
          tail.next = newNode;
          newNode.last = tail;
          tail = newNode;
        }
      }
      public void moveNodeToTail(DoubleNode node) {
        if (tail == node) {
          return;
        }
        if (head == node) {
          head = node.next;
          head.last = null;
        } else {
          node.last.next = node.next;
          node.next.last = node.last;
        }
        node.last = tail;
        node.next = null;
        tail.next = node;
        tail = node;
      }
      public DoubleNode removeHead() {
        if (head == null) {
          return null;
        }
        DoubleNode ans = head;
        if (head == tail) {
          head = null;
          tail = null;
        } else {
          head = ans.next;
          ans.next = null;
          head.last = null;
        }
        return ans;
      }
    }
    private HashMap<Integer, DoubleNode> keyNodeMap;
    private DoubleList nodeList;
    private final int capacity;
    public LRUCache(int cap) {
      keyNodeMap = new HashMap<>();
      nodeList = new DoubleList();
      capacity = cap;
    }
    public int get(int key) {
      if (keyNodeMap.containsKey(key)) {
        DoubleNode ans = keyNodeMap.get(key);
        nodeList.moveNodeToTail(ans);
        return ans.val;
      }
      return -1;
    }
    public void put(int key, int value) {
      if (keyNodeMap.containsKey(key)) {
        DoubleNode node = keyNodeMap.get(key);
        node.val = value;
        nodeList.moveNodeToTail(node);
      } else {
        if (keyNodeMap.size() == capacity) {
          keyNodeMap.remove(nodeList.removeHead().key);
        }
        DoubleNode newNode = new DoubleNode(key, value);
        keyNodeMap.put(key, newNode);
        nodeList.addNode(newNode);
      }
    }
  }
}

code3 380. O(1) 时间插入、删除和获取随机元素

// 插入、删除和获取随机元素O(1)时间的结构

// 测试链接 : https://leetcode.cn/problems/insert-delete-getrandom-o1/

思路:HashMap+动态数组 remove()方法使用最后一个元素填补中间的空缺

package class035;
import java.util.ArrayList;
import java.util.HashMap;
// 插入、删除和获取随机元素O(1)时间的结构
public class Code03_InsertDeleteRandom {
  // 测试链接 : https://leetcode.cn/problems/insert-delete-getrandom-o1/
  class RandomizedSet {
    public HashMap<Integer, Integer> map;
    public ArrayList<Integer> arr;
    public RandomizedSet() {
      map = new HashMap<>();
      arr = new ArrayList<>();
    }
    public boolean insert(int val) {
      if (map.containsKey(val)) {
        return false;
      }
      map.put(val, arr.size());
      arr.add(val);
      return true;
    }
    public boolean remove(int val) {
      if (!map.containsKey(val)) {
        return false;
      }
      int valIndex = map.get(val);
      int endValue = arr.get(arr.size() - 1);
      map.put(endValue, valIndex);
      arr.set(valIndex, endValue);
      map.remove(val);
      arr.remove(arr.size() - 1);
      return true;
    }
    public int getRandom() {
      return arr.get((int) (Math.random() * arr.size()));
    }
  }
}

code4 381. O(1) 时间插入、删除和获取随机元素 - 允许重复

// 插入、删除和获取随机元素O(1)时间且允许有重复数字的结构

// 测试链接 :

// https://leetcode.cn/problems/insert-delete-getrandom-o1-duplicates-allowed/

思路:HashMap<Integer,HashSet< Integer>>+动态数组 remove()方法使用最后一个元素填补中间的空缺

package class035;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
// 插入、删除和获取随机元素O(1)时间且允许有重复数字的结构
public class Code04_InsertDeleteRandomDuplicatesAllowed {
  // 测试链接 :
  // https://leetcode.cn/problems/insert-delete-getrandom-o1-duplicates-allowed/
  class RandomizedCollection {
    public HashMap<Integer, HashSet<Integer>> map;
    public ArrayList<Integer> arr;
    public RandomizedCollection() {
      map = new HashMap<>();
      arr = new ArrayList<>();
    }
    public boolean insert(int val) {
      arr.add(val);
      HashSet<Integer> set = map.getOrDefault(val, new HashSet<Integer>());
      set.add(arr.size() - 1);
      map.put(val, set);
      return set.size() == 1;
    }
    public boolean remove(int val) {
      if (!map.containsKey(val)) {
        return false;
      }
      HashSet<Integer> valSet = map.get(val);
      int valAnyIndex = valSet.iterator().next();
      int endValue = arr.get(arr.size() - 1);
      if (val == endValue) {
        valSet.remove(arr.size() - 1);
      } else {
        HashSet<Integer> endValueSet = map.get(endValue);
        endValueSet.add(valAnyIndex);
        arr.set(valAnyIndex, endValue);
        endValueSet.remove(arr.size() - 1);
        valSet.remove(valAnyIndex);
      }
      arr.remove(arr.size() - 1);
      if (valSet.isEmpty()) {
        map.remove(val);
      }
      return true;
    }
    public int getRandom() {
      return arr.get((int) (Math.random() * arr.size()));
    }
  }
}

code5 295. 数据流的中位数

// 快速获得数据流的中位数的结构

// 测试链接 : https://leetcode.cn/problems/find-median-from-data-stream/

思路:大根堆+小根堆

package class035;
import java.util.PriorityQueue;
// 快速获得数据流的中位数的结构
public class Code05_MedianFinder {
  // 测试链接 : https://leetcode.cn/problems/find-median-from-data-stream/
  class MedianFinder {
    private PriorityQueue<Integer> maxHeap;
    private PriorityQueue<Integer> minHeap;
    public MedianFinder() {
      maxHeap = new PriorityQueue<>((a, b) -> b - a);
      minHeap = new PriorityQueue<>((a, b) -> a - b);
    }
    public void addNum(int num) {
      if (maxHeap.isEmpty() || maxHeap.peek() >= num) {
        maxHeap.add(num);
      } else {
        minHeap.add(num);
      }
      balance();
    }
    public double findMedian() {
      if (maxHeap.size() == minHeap.size()) {
        return (double) (maxHeap.peek() + minHeap.peek()) / 2;
      } else {
        return maxHeap.size() > minHeap.size() ? maxHeap.peek() : minHeap.peek();
      }
    }
    private void balance() {
      if (Math.abs(maxHeap.size() - minHeap.size()) == 2) {
        if (maxHeap.size() > minHeap.size()) {
          minHeap.add(maxHeap.poll());
        } else {
          maxHeap.add(minHeap.poll());
        }
      }
    }
  }
}

code6 895. 最大频率栈

// 最大频率栈

// 测试链接 : https://leetcode.cn/problems/maximum-frequency-stack/

思路:多级链表+HashMap

package class035;
import java.util.ArrayList;
import java.util.HashMap;
// 最大频率栈
public class Code06_MaximumFrequencyStack {
  // 测试链接 : https://leetcode.cn/problems/maximum-frequency-stack/
  class FreqStack {
    // 出现的最大次数
    private int topTimes;
    // 每层节点
    private HashMap<Integer, ArrayList<Integer>> cntValues = new HashMap<>();
    // 每一个数出现了几次
    private HashMap<Integer, Integer> valueTimes = new HashMap<>();
    public void push(int val) {
      valueTimes.put(val, valueTimes.getOrDefault(val, 0) + 1);
      int curTopTimes = valueTimes.get(val);
      if (!cntValues.containsKey(curTopTimes)) {
        cntValues.put(curTopTimes, new ArrayList<>());
      }
      ArrayList<Integer> curTimeValues = cntValues.get(curTopTimes);
      curTimeValues.add(val);
      topTimes = Math.max(topTimes, curTopTimes);
    }
    public int pop() {
      ArrayList<Integer> topTimeValues = cntValues.get(topTimes);
      int ans = topTimeValues.remove(topTimeValues.size() - 1);
      if (topTimeValues.size() == 0) {
        cntValues.remove(topTimes--);
      }
      int times = valueTimes.get(ans);
      if (times == 1) {
        valueTimes.remove(ans);
      } else {
        valueTimes.put(ans, times - 1);
      }
      return ans;
    }
  }
}

code7 432. 全 O(1) 的数据结构

// 全O(1)的数据结构

// 测试链接 : https://leetcode.cn/problems/all-oone-data-structure/

思路:HashMap+双向链表

package class035;
import java.util.HashMap;
import java.util.HashSet;
// 全O(1)的数据结构
public class Code07_AllO1 {
  // 测试链接 : https://leetcode.cn/problems/all-oone-data-structure/
  class AllOne {
    class Bucket {
      public HashSet<String> set;
      public int cnt;
      public Bucket last;
      public Bucket next;
      public Bucket(String s, int c) {
        set = new HashSet<>();
        set.add(s);
        cnt = c;
      }
    }
    private void insert(Bucket cur, Bucket pos) {
      cur.next.last = pos;
      pos.next = cur.next;
      cur.next = pos;
      pos.last = cur;
    }
    private void remove(Bucket cur) {
      cur.last.next = cur.next;
      cur.next.last = cur.last;
    }
    Bucket head;
    Bucket tail;
    HashMap<String, Bucket> map;
    public AllOne() {
      head = new Bucket("", 0);
      tail = new Bucket("", Integer.MAX_VALUE);
      head.next = tail;
      tail.last = head;
      map = new HashMap<>();
    }
    public void inc(String key) {
      if (!map.containsKey(key)) {
        if (head.next.cnt == 1) {
          map.put(key, head.next);
          head.next.set.add(key);
        } else {
          Bucket newBucket = new Bucket(key, 1);
          map.put(key, newBucket);
          insert(head, newBucket);
        }
      } else {
        Bucket bucket = map.get(key);
        if (bucket.next.cnt == bucket.cnt + 1) {
          map.put(key, bucket.next);
          bucket.next.set.add(key);
        } else {
          Bucket newBucket = new Bucket(key, bucket.cnt + 1);
          map.put(key, newBucket);
          insert(bucket, newBucket);
        }
        bucket.set.remove(key);
        if (bucket.set.isEmpty()) {
          remove(bucket);
        }
      }
    }
    public void dec(String key) {
      Bucket bucket = map.get(key);
      if (bucket.cnt == 1) {
        map.remove(key);
      } else {
        if (bucket.last.cnt == bucket.cnt - 1) {
          map.put(key, bucket.last);
          bucket.last.set.add(key);
        } else {
          Bucket newBucket = new Bucket(key, bucket.cnt - 1);
          map.put(key, newBucket);
          insert(bucket.last, newBucket);
        }
      }
      bucket.set.remove(key);
      if (bucket.set.isEmpty()) {
        remove(bucket);
      }
    }
    public String getMaxKey() {
      return tail.last.set.iterator().next();
    }
    public String getMinKey() {
      return head.next.set.iterator().next();
    }
  }
}


相关文章
|
1月前
|
机器学习/深度学习 存储 算法
【算法与数据结构】复杂度深度解析(超详解)
【算法与数据结构】复杂度深度解析(超详解)
【算法与数据结构】复杂度深度解析(超详解)
|
1月前
|
存储 算法 索引
【算法与数据结构】队列的实现详解
【算法与数据结构】队列的实现详解
159 0
|
1月前
|
算法
【算法与数据结构】二叉树(前中后)序遍历2
【算法与数据结构】二叉树(前中后)序遍历
|
3天前
|
机器学习/深度学习 存储 算法
数据结构与算法 动态规划(启发式搜索、遗传算法、强化学习待完善)
数据结构与算法 动态规划(启发式搜索、遗传算法、强化学习待完善)
10 1
|
7天前
|
搜索推荐 C语言
【C语言/数据结构】排序(归并排序|计数排序|排序算法复杂度)
【C语言/数据结构】排序(归并排序|计数排序|排序算法复杂度)
11 0
|
7天前
|
存储 算法
Leetcode 30天高效刷数据结构和算法 Day1 两数之和 —— 无序数组
给定一个无序整数数组和目标值,找出数组中和为目标值的两个数的下标。要求不重复且可按任意顺序返回。示例:输入nums = [2,7,11,15], target = 9,输出[0,1]。暴力解法时间复杂度O(n²),优化解法利用哈希表实现,时间复杂度O(n)。
19 0
|
14天前
|
存储 机器学习/深度学习 算法
|
17天前
|
存储 算法 Python
程序设计的艺术:算法与数据结构的魅力
程序设计的艺术:算法与数据结构的魅力
8 0
|
18天前
|
存储 算法
数据结构开篇(普普通通浅浅聊数据结构)什么是数据结构 、什么是算法、重要性、如何学好数据结构呢
数据结构开篇(普普通通浅浅聊数据结构)什么是数据结构 、什么是算法、重要性、如何学好数据结构呢
|
25天前
|
存储 人工智能 算法
有哪些数据结构与算法是程序员必须要掌握的?——“数据结构与算法”
有哪些数据结构与算法是程序员必须要掌握的?——“数据结构与算法”