目录

  • 和为K的子数组
    • 1 题目描述
    • 2 解题(Java)
    • 3 复杂性分析
  • 目标和
    • 1 题目描述
    • 2 解题(Java)
    • 3 复杂性分析
  • 前 K 个高频元素
    • 1 题目描述
    • 2 解题(Java)
    • 3 复杂性分析
  • 最长连续序列
    • 1 题目描述
    • 2 解题(Java)
    • 3 复杂性分析
  • 扑克牌中的顺子
    • 1 题目描述
    • 2 解题(Java)
    • 3 复杂性分析
  • 最小覆盖子串
    • 1 题目描述
    • 2 解题(Java)
    • 3 复杂性分析
  • 字母异位词分组
    • 1 题目描述
    • 2 解题(Java)
    • 3 复杂性分析
  • 两数之和
    • 1 题目描述
    • 2 解题(Java)
    • 3 复杂度分析
  • 复杂链表的复制
    • 1 题目描述
    • 2 解题(java)
    • 3 复杂性分析
  • 有效的括号
    • 1 题目描述
    • 2 解题(Java)
    • 3 复杂性分析
  • 能否连接形成数组
    • 1 题目描述
    • 2 解题(Java)
    • 3 复杂性分析
  • 最长不含重复字符的子字符串
    • 1 题目描述
    • 2 解题(Java)
    • 3 复杂性分析
  • 第一个只出现一次的字符
    • 1 题目描述
    • 2 解题(Java)
    • 3 复杂性分析
  • 电话号码的字母组合
    • 1 题目描述
    • 2 解题(Java)
      • 2.1 解题思路
      • 2.2 代码
    • 3 复杂性分析
  • 设计LRU缓存结构
    • 1 题目描述
    • 2 解题(Java)

和为K的子数组

1 题目描述

给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。

示例 1 :

输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。

说明 :

  1. 数组的长度为 [1, 20,000]。
  2. 数组中元素的范围是 [-1000, 1000] ,且整数 k 的范围是 [-1e7, 1e7]。

2 解题(Java)

前缀和 + 哈希表:

class Solution {public int subarraySum(int[] nums, int k) {Map<Integer, Integer> cache = new HashMap<>();int count = 0, pre = 0;cache.put(0, 1);for (int num : nums) {pre += num;count += cache.getOrDefault(pre - k, 0);cache.put(pre, cache.getOrDefault(pre, 0) + 1);}return count;}
}

3 复杂性分析

  • 时间复杂度:O(n);
  • 空间复杂度:O(n);

目标和

1 题目描述

给你一个整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 ‘+’ 或 ‘-’ ,然后串联起所有整数,可以构造一个 表达式 :

  • 例如,nums = [2, 1] ,可以在 2 之前添加 ‘+’ ,在 1 之前添加 ‘-’ ,然后串联起来得到表达式 “+2-1” 。

返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

示例 1

输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 3 。
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3

示例 2

输入:nums = [1], target = 1
输出:1

提示

  • 1 <= nums.length <= 20
  • 0 <= nums[i] <= 1000
  • 0 <= sum(nums[i]) <= 1000
  • -1000 <= target <= 1000

2 解题(Java)

树的后序遍历+记忆化搜索

class Solution {Map<String, Integer> cache = new HashMap<>();int target;int[] nums;public int findTargetSumWays(int[] nums, int target) {this.target = target;this.nums = nums;return dfs(0, nums[0]) + dfs(0, -nums[0]);}int dfs(int index, int sum) {String key = index + "_" + sum;if (cache.containsKey(key)) return cache.get(key);if (index == nums.length - 1) {cache.put(key, sum == target ? 1 : 0);return cache.get(key);}int left = dfs(index + 1, sum + nums[index + 1]);int right = dfs(index + 1, sum - nums[index + 1]);cache.put(key, left + right);return cache.get(key);}
}

3 复杂性分析

前 K 个高频元素

1 题目描述

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

示例 1:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

示例 2:

输入: nums = [1], k = 1
输出: [1]

提示

  • 1 <= nums.length <= 105
  • k 的取值范围是 [1, 数组中不相同的元素的个数]
  • 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的

进阶:你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。

2 解题(Java)

HashMap + 堆排序:

class Solution {public int[] topKFrequent(int[] nums, int k) {Map<Integer, Integer> map = new HashMap<Integer, Integer>();for (int num : nums) {map.put(num, map.getOrDefault(num, 0) + 1);}// int[] 的第一个元素代表数组的值,第二个元素代表了该值出现的次数,根据第二个元素设计小根堆PriorityQueue<int[]> heap = new PriorityQueue<int[]>((o1, o2) -> o1[1] - o2[1]);for (Integer num : map.keySet()) {if (heap.size() == k) {if (heap.peek()[1] < map.get(num)) {heap.poll();heap.offer(new int[]{num, map.get(num)});}} else {heap.offer(new int[]{num, map.get(num)});}}int[] res = new int[k];int i = 0;while (!heap.isEmpty()) res[i++] = heap.poll()[0];return res;}
}

3 复杂性分析

  • 时间复杂度:O(Nlogk),其中 N 为数组的长度。我们首先遍历原数组,并使用哈希表记录出现次数,需 O(N) 时间;随后遍历HashMap,由于堆的大小至多为 k,因此每次堆操作需要 O(logk) 的时间,需 O(Nlogk)的时间;总时间复杂度为O(Nlogk);
  • 空间复杂度:O(N)。哈希表 O(N),堆 O(k),总 O(N);

最长连续序列

1 题目描述

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

进阶:你可以设计并实现时间复杂度为 O(n) 的解决方案吗?

示例 1

输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

示例 2

输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9

提示

  • 0 <= nums.length <= 10 ^ 4
  • -10 ^ 9 <= nums[i] <= 10 ^ 9

2 解题(Java)

class Solution {public int longestConsecutive(int[] nums) {int max = 0;Set<Integer> set = new HashSet<>();for (int num : nums) set.add(num);for (int num : set) {if (!set.contains(num - 1)) {int temp = 1;while (set.contains(++num)) temp++;max = Math.max(max, temp);}}return max;}
}

3 复杂性分析

  • 时间复杂度O(n):外层循环需要 O(n) 的时间复杂度;只有当一个数是连续序列的第一个数的情况下才会进入内层循环,然后在内层循环中匹配连续序列中的数,因此数组中的每个数只会进入内层循环1次,时间复杂度为O(n) ;因此总时间复杂度为 O(n);
  • 空间复杂度O(n):Set存储数组中的数需要 O(n) 空间;

扑克牌中的顺子

1 题目描述

从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。

示例 1:

输入: [1,2,3,4,5]
输出: True

示例 2:

输入: [0,0,1,2,5]
输出: True

限制:

  1. 数组长度为 5
  2. 数组的数取值为 [0, 13]

2 解题(Java)

class Solution {public boolean isStraight(int[] nums) {Set<Integer> repeat = new HashSet<>();int max = Integer.MIN_VALUE, min = Integer.MAX_VALUE;for(int num : nums) {if(num == 0) continue; // 跳过大小王max = Math.max(max, num); // 最大牌min = Math.min(min, num); // 最小牌if(!repeat.add(num)) return false; // 添加此牌至set,若有重复,返回 false}return max - min < 5; // 最大牌 - 最小牌 < 5 则可构成顺子}
}

3 复杂性分析

  • 时间复杂度 O(N) = O(5) = O(1): 其中 N 为 nums 长度,本题中 N≡5 ,遍历数组使用 O(N) 时间;
  • 空间复杂度 O(N) = O(5) = O(1): 用于判重的辅助 Set 占用 O(N) 额外空间;

最小覆盖子串

1 题目描述

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。

注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例 1

输入:s = “ADOBECODEBANC”, t = “ABC”
输出:“BANC”

示例 2

输入:s = “a”, t = “a”
输出:“a”

提示

  • 1 <= s.length, t.length <= 10 ^ 5
  • s 和 t 由英文字母组成

进阶:你能设计一个在 o(n) 时间内解决此问题的算法吗?

2 解题(Java)

class Solution {public String minWindow(String s, String t) {Map<Character, Integer> tMap = new HashMap<>();Map<Character, Integer> windowMap = new HashMap<>();// 记录t中所有字符及其出现的次数for (char c : t.toCharArray()) {tMap.put(c, tMap.getOrDefault(c, 0) + 1);}int left = 0, right = 0;// 记录窗口中满足条件的字符个数int count = 0;// 记录最小覆盖子串的起始索引及长度int start = 0, minLength = Integer.MAX_VALUE;while (right < s.length()) {char c = s.charAt(right);// 判断取出的字符是否在t中if (tMap.containsKey(c)) {windowMap.put(c, windowMap.getOrDefault(c, 0) + 1);// 判断取出的字符在窗口中出现的次数是否与t中该字符的出现次数相同if (windowMap.get(c).equals(tMap.get(c))) {count++;}}// 找到符合条件的子串后,尝试缩小窗口while (count == tMap.size()) {if (right - left + 1 < minLength) {start = left;minLength = right - left + 1;}char c1 = s.charAt(left);left++;if (tMap.containsKey(c1)) {if (windowMap.get(c1).equals(tMap.get(c1))) {count--;}windowMap.put(c1, windowMap.get(c1) - 1);}}// 尝试新方案right++;}return minLength == Integer.MAX_VALUE ? "" : s.substring(start, start + minLength);}
}

3 复杂性分析

  • 时间复杂度O(n):n为s的长度,线性遍历一次s;
  • 空间复杂度O(n):HashMap所占空间;

字母异位词分组

1 题目描述

给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

示例:

输入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
输出:
[
[“ate”,“eat”,“tea”],
[“nat”,“tan”],
[“bat”]
]

说明

  • 所有输入均为小写字母。
  • 不考虑答案输出的顺序。

2 解题(Java)

class Solution {public List<List<String>> groupAnagrams(String[] strs) {Map<String, List<String>> map = new HashMap<>();for (String str :strs) {char[] array = str.toCharArray();Arrays.sort(array);String key = new String(array);List<String> list = map.getOrDefault(key, new ArrayList<>());list.add(str);map.put(key, list);}return new ArrayList<List<String>>(map.values());}
}

3 复杂性分析

  • 时间复杂度O(nklogk):其中 n 是 strs 中的字符串的数量,k 是 strs 中的字符串的的最大长度。需要遍历 n 个字符串,对于每个字符串,需要 O(klogk) 的时间进行排序以及 O(1) 的时间更新哈希表,因此总时间复杂度是 O(nklogk);
  • 空间复杂度O(nk):其中 n 是 strs 中的字符串的数量,k 是 strs 中的字符串的的最大长度,需要用哈希表存储全部字符串;

两数之和

1 题目描述

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例:

给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

2 解题(Java)

class Solution {public int[] twoSum(int[] nums, int target) {if (nums == null || nums.length < 2) return new int[0];Map<Integer,Integer> map = new HashMap<>();for (int i=0; i<nums.length; i++) {if (map.containsKey(target-nums[i])) {return new int[]{map.get(target-nums[i]), i};}map.put(nums[i], i);}return new int[0];}
}

3 复杂度分析

  • 时间复杂度:O(N),其中 N是数组中的元素数量。对于每一个元素 x,我们可以 O(1)地寻找 target - x。
  • 空间复杂度:O(N),其中 N 是数组中的元素数量,主要为哈希表的开销。

复杂链表的复制

1 题目描述

请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。

示例 1:

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

示例 2:

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]

示例 3:

输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]

示例 4:

输入:head = []
输出:[]

解释:给定的链表为空(空指针),因此返回 null。

提示:

  • -10000 <= Node.val <= 10000
  • Node.random 为空(null)或指向链表中的节点。
  • 节点数目不超过 1000 。

2 解题(java)

题意理解

本题的意思是复制一个链表并返回,在这里,复制的意思是指 深拷贝(Deep Copy),事实上,与此对应的还有 浅拷贝,它们的区别是:

  1. 浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。
  2. 但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
/*
// Definition for a Node.
class Node {int val;Node next;Node random;public Node(int val) {this.val = val;this.next = null;this.random = null;}
}
*/
class Solution {public Node copyRandomList(Node head) {if(head == null) return null;Node cur = head;Map<Node, Node> map = new HashMap<>();// 3. 复制各节点,并建立 “原节点 -> 新节点” 的 Map 映射while(cur != null) {map.put(cur, new Node(cur.val));cur = cur.next;}cur = head;// 4. 构建新链表的 next 和 random 指向while(cur != null) {map.get(cur).next = map.get(cur.next);map.get(cur).random = map.get(cur.random);cur = cur.next;}// 5. 返回新链表的头节点return map.get(head);}
}

3 复杂性分析

  • 时间复杂度 O(N) : 两轮遍历链表,使用 O(N)时间。
  • 空间复杂度 O(N) : 哈希表空间。

有效的括号

1 题目描述

给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 注意空字符串可被认为是有效字符串。

示例 1:

输入: “()”
输出: true

示例 2:

输入: “()[]{}”
输出: true

示例 3:

输入: “(]”
输出: false

示例 4:

输入: “([)]”
输出: false

2 解题(Java)

栈和哈希表:

class Solution {public boolean isValid(String s) {int n = s.length();if (n % 2 == 1) {return false;}Map<Character, Character> pairs = new HashMap<>() {{put(')', '(');put(']', '[');put('}', '{');}};Deque<Character> stack = new LinkedList<>();for (int i = 0; i < n; i++) {char ch = s.charAt(i);if (pairs.containsKey(ch)) {if (stack.isEmpty() || stack.peek() != pairs.get(ch)) {return false;}stack.pop();} else {stack.push(ch);}}return stack.isEmpty();}
}

3 复杂性分析

  • 时间复杂度 O(N):需要遍历一遍 s;
  • 空间复杂度 O(N):栈使用线性的空间大小;

能否连接形成数组

1 题目描述

给你一个整数数组 arr ,数组中的每个整数互不相同 。另有一个由整数数组构成的数组 pieces,其中的整数也互不相同 。请你以任意顺序连接 pieces 中的数组以形成 arr 。但是,不允许对每个数组 pieces[i] 中的整数重新排序。

如果可以连接 pieces 中的数组形成 arr ,返回 true ;否则,返回 false 。

示例 1:

输入:arr = [85], pieces = [[85]]
输出:true

示例 2:

输入:arr = [15,88], pieces = [[88],[15]]
输出:true
解释:依次连接 [15] 和 [88]

示例 3:

输入:arr = [49,18,16], pieces = [[16,18,49]]
输出:false
解释:即便数字相符,也不能重新排列pieces[0]

示例 4:

输入:arr = [91,4,64,78], pieces = [[78],[4,64],[91]]
输出:true
解释:依次连接[91]、[4,64] 和 [78]

示例 5:

输入:arr = [1,3,5,7], pieces = [[2,4,6,8]]
输出:false

提示:

  • 1 <= pieces.length <= arr.length <= 100
  • sum(pieces[i].length) == arr.length
  • 1 <= pieces[i].length <= arr.length
  • 1 <= arr[i], pieces[i][j] <= 100
  • arr 中的整数 互不相同
  • pieces 中的整数 互不相同(也就是说,如果将 pieces 扁平化成一维数组,数组中的所有整数互不相同)

2 解题(Java)

class Solution {public boolean canFormArray(int[] arr, int[][] pieces) {// 构造哈希表,key为pieces中各数组的首元素,值为对应的各数组Map<Integer, int[]> map = new HashMap<>();for (int[] piece : pieces) {map.put(piece[0], piece);}// 遍历arr数组进行判定int i = 0;while(i < arr.length) {int curVal = arr[i];// 如果map中的键包含curVal,继续判定,否则返回falseif (map.containsKey(curVal)) {// 取出curVal对应的数组,继续内循环判定,如果有一个对应不上,返回false;内循环判定成功后,回到外循环,开启下一次判定int[] piece = map.get(curVal);for (int value : piece) {if (arr[i] == value) {i++;} else {return false;}}} else {return false;}}// 前面的判定没有问题,返回truereturn true;}
}

3 复杂性分析

  • 时间复杂度O(N):N是数组arr的长度,循环遍历1次;
  • 空间复杂度O(N):哈希表存储pieces,占用O(N)空间;

最长不含重复字符的子字符串

1 题目描述

请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。

示例 1:

输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

示例 2:

输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:

输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

提示:

s.length <= 40000

2 解题(Java)

class Solution {public int lengthOfLongestSubstring(String s) {Map<Character, Integer> dic = new HashMap<>();int res = 0, tmp = 0;for(int right = 0; right < s.length(); right++) {int left = dic.getOrDefault(s.charAt(right), -1); // 获取索引leftdic.put(s.charAt(right), right); // 更新哈希表tmp = tmp < right - left ? tmp + 1 : right - left; // dp[right-1] -> dp[right]res = Math.max(res,tmp); }return res;}
}

3 复杂性分析

  • 时间复杂度 O(N) : 其中 N 为字符串长度,动态规划需遍历计算字符串各字符;
  • 空间复杂度 O(1) : 字符的 ASCII 码范围为 0 ~ 127 ,哈希表 dic 最多使用 O(128)=O(1)大小的额外空间;

第一个只出现一次的字符

1 题目描述

在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。

示例:

s = “abaccdeff”
返回 “b”

s = “”
返回 " "

限制:

0 <= s 的长度 <= 50000

2 解题(Java)

class Solution {public char firstUniqChar(String s) {Map<Character, Boolean> dic = new HashMap<>();char[] cs = s.toCharArray();for (char c : cs) {dic.put(c, !dic.containsKey(c));}for (char c : cs) {if (dic.get(c)) return c;}return ' ';}
}

3 复杂性分析

  • 时间复杂度 O(N) : N 为字符串 s 的长度;需遍历 s 两轮,使用 O(N) ;
  • 空间复杂度 O(1) : 由于题目指出 s 只包含小写字母,因此最多有 26 个不同字符,HashMap 存储需占用 O(26) = O(1) 的额外空间。

电话号码的字母组合

1 题目描述

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。


示例:

输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

说明:

尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。

2 解题(Java)

2.1 解题思路

回溯算法:

  1. 用一个哈希表存储每个数字对应的所有字母;
  2. 回溯过程维护一个StringBuilder ans,表示字母组合;
  3. ans初始为空,每次取电话号码的一位数字,然后从哈希表中获得该数字对应的所有字母,并将其中一个加入ans中;
  4. 继续处理电话号码后一位数字,直到处理完电话号码的所有数字,即得到一个完整的字母组合,并将其加入结果res中;
  5. 回退,遍历其余的字母组合,依次加入res中,返回res即可;

注:

回溯算法主要用于寻找所有的可行解,如果发现一个解不可行,再回溯寻找其它解。而在本题中,由于每个数字对应的每个字母都可能进入字母组合,因此不存在不可行的解,相当于穷举所有解。

2.2 代码

class Solution {List<String> res = new ArrayList<>();StringBuilder ans = new StringBuilder();Map<Character, String> dic = new HashMap<Character, String>() {{put('2', "abc");put('3', "def");put('4', "ghi");put('5', "jkl");put('6', "mno");put('7', "pqrs");put('8', "tuv");put('9', "wxyz");}};String digits;public List<String> letterCombinations(String digits) {this.digits = digits;if (digits.length() == 0) return res;backTrack(0);return res;}public void backTrack(int index) {if (index == digits.length()) {res.add(ans.toString());} else {String letters = dic.get(digits.charAt(index));for (int i=0; i<letters.length(); i++) {ans.append(letters.charAt(i));backTrack(index+1);ans.deleteCharAt(index);}}}
}

3 复杂性分析

  • 时间复杂度O(3 ^ M * 4 ^ N):其中 M 是输入中对应3个字母的数字个数(包括数字 2、3、4、5、6、8),N 是输入中对应4个字母的数字个数(包括数字 7、9),当输入包含M个对应3个字母的数字和N个对应4个字母的数字时,不同的字母组合共有3 ^ M * 4 ^ N种,需要遍历每一种字母组合;
  • 空间复杂度O(M + N):其中M是输入中对应3个字母的数字个数,N是输入中对应4个字母的数字个数,M+N是输入数字的总个数。除了返回值以外,空间复杂度主要取决于哈希表以及回溯过程中的递归调用层数,哈希表的大小与输入无关,可以看成常数,递归调用层数最大为M+N;

设计LRU缓存结构

1 题目描述

设计LRU缓存结构,该结构在构造时确定大小,假设大小为K,并有如下两个功能

  • set(key, value):将记录(key, value)插入该结构
  • get(key):返回key对应的value值

要求

  1. set和get方法的时间复杂度为O(1);
  2. 某个key的set或get操作一旦发生,认为这个key的记录成了最常使用的;
  3. 当缓存的大小超过K时,移除最不经常使用的记录,即set或get最久远的;

解释

  1. 若opt=1,接下来两个整数x, y,表示set(x, y);
  2. 若opt=2,接下来一个整数x,表示get(x),若x未出现过或已被移除,则返回-1;
  3. 对于每个opt2,输出一个答案;

示例1

输入

[[1,1,1],[1,2,2],[1,3,2],[2,1],[1,4,4],[2,2]],3

返回值

[1,-1]

说明

第一次操作后:最常使用的记录为(“1”, 1) 第二次操作后:最常使用的记录为(“2”, 2),(“1”, 1)变为最不常用的
第三次操作后:最常使用的记录为(“3”, 2),(“1”, 1)还是最不常用的 第四次操作后:最常用的记录为(“1”, 1),(“2”, 2)变为最不常用的
第五次操作后:大小超过了3,所以移除此时最不常使用的记录(“2”, 2),加入记录(“4”,4),并且为最常使用的记录,然后(“3”, 2)变为最不常使用的记录

备注

2 解题(Java)

import java.util.*;public class Solution {private Map<Integer, DLinkedNode> cache = new HashMap<>();private int k;// 使用伪头部和伪尾部节点private DLinkedNode head = new DLinkedNode();private DLinkedNode tail = new DLinkedNode();public int[] LRU (int[][] operators, int k) {this.k = k;head.next = tail;tail.prev = head;int len = 0;for (int i=0; i<operators.length; i++) {if (operators[i][0] == 2) len++;}int[] res = new int[len];for(int i = 0, j = 0; i < operators.length; i++) {if(operators[i][0] == 1) {set(operators[i][1], operators[i][2]);} else {res[j++] = get(operators[i][1]);}}return res;}public int get(int key) {if (cache.containsKey(key)) {DLinkedNode node = cache.get(key);moveToHead(node);return node.value;}return -1;}public void set(int key, int value) {if (cache.containsKey(key)) {DLinkedNode node = cache.get(key);node.value = value;moveToHead(node);} else {if (cache.size() == k) {removeTail();}DLinkedNode node = new DLinkedNode(key, value);cache.put(key, node);addToHead(node);}}private void addToHead(DLinkedNode node) {node.prev = head;node.next = head.next;head.next.prev = node;head.next = node;}private void moveToHead(DLinkedNode node) {node.prev.next = node.next;node.next.prev = node.prev;addToHead(node);}private void removeTail() {int rk = tail.prev.key;tail.prev.prev.next = tail;tail.prev = tail.prev.prev;cache.remove(rk);}class DLinkedNode {int key, value;DLinkedNode prev, next;public DLinkedNode() {}public DLinkedNode(int key, int value) {this.key = key; this.value = value;}}
}

Leetcode_Map、Set相关推荐

  1. 专利审查指南(2010)

    专利审查指南(2010) http://www.chinalaw.gov.cn/article/fgkd/xfg/gwybmgz/201004/20100400253035.shtml来源国务院法制办 ...

  2. 湖南省中职学业水平测试试题信息技术

    试题: 1.按照指法要求,击打空格键,应使用( ). A.左手和右手的食指,因食指最灵活 B.左手或右手的拇指 C.左手或右手的中指 D.左手或右手的无名指 2.显示器的清晰度是由( )决定的. A. ...

  3. Photoshop入门与进阶实例:1.4 图层的概念和基本操作

    1.认识图层 图层功能被誉为Photoshop的灵魂,这个比喻一点也不夸张!图层在我们使用Photoshop进行图像处理中,具有十分重要的地位,也是最常用到的功能之一.掌握图层的概念是我们学习Phot ...

  4. 2023年你最值得了解的信息技术-AI篇(二)

    20688 北京朗阁信息技术有限公司 企业服务  前沿技术 北京市 mailkey 专注云企业邮件领域的产品,随云服务而生. 未融资 MailKey 是北京朗阁信息技术有限公司(以下简称"朗 ...

  5. 程序主动进行电话短信报警,自定义电话、短信、钉钉报警通知

    程序主动进行电话短信报警,自定义电话.短信.钉钉报警通知 一. 规则说明 这里我们要利用到阿里云的云监控的手段,有一个叫做事件监控的东西,可以通过自定义事件上传来进行监控报警. 流程: 程序发现错误 ...

  6. nginx配置http、https访问,nginx指定ssl证书,阿里云腾讯云华为云设置nginx https安全访问

    nginx配置http.https访问 要设置https访问需要从对应的云厂商申请证书,并下载Nginx证书到服务器. 我这里从阿里云申请了免费的域名证书,然后将证书放置在服务器的/etc/ssl/. ...

  7. 在Chrome中打开网页时出现以下问题 您的连接不是私密连接 攻击者可能会试图从 x.x.x.x 窃取您的信息(例如:密码、通讯内容或信用卡信息)

    现象:在Chrome中打开网页时出现以下问题 您的连接不是私密连接 攻击者可能会试图从 x.x.x.x 窃取您的信息(例如:密码.通讯内容或信用卡信息). 当点开"了解详情"后显示 ...

  8. 使用第三方SDK(如微信、qq、快看、头条等),调用接口405 Method Not Allowed

    使用第三方SDK(如微信.qq.快看.头条等),调用接口405 Method Not Allowed 错误描述:postman请求正常,但客户端调用后接口没有反应,但返回了405错误. 解决方法:第三 ...

  9. OpenAPI使用(swagger3),Kotlin使用swagger3,Java使用swagger3,gradle、Maven使用swagger3

    OpenAPI使用(swagger3) demo见Gitte 一.背景及名词解释 OpenAPI是规范的正式名称.规范的开发工作于2015年启动,当时SmartBear(负责Swagger工具开发的公 ...

最新文章

  1. 去掉hyperlink下划线
  2. python ImportError: No module named unittest2
  3. 《Linux内核原理与分析》第三周作业
  4. 5年,14款近满分神作,这个独立团队打造了他们的游戏宇宙
  5. SAP Spartacus Ngrx 使用的一些准则
  6. Svn正确的使用方法
  7. Halcon算子学习:create_sheet_of_light_model
  8. C/C++ 指针的深入理解
  9. 强烈的打击感jinbiguandan
  10. python定时下载FTP指定文件
  11. 【kmp】POJ-3461 Oulipo
  12. Alpha,Beta,RC,RTM,EVAL,CTP,OEM,RTL,VOL
  13. 高级API 快速入门之第八章 多线程02
  14. 三极管放大电路基础知识
  15. ROS主从机通信经验总结
  16. c语言作业系统课设设计,C语言程序课程设计心得体会
  17. macOS的计时器:Clocker for Mac
  18. pip安装python库总提示下载超时read timed out的解决办法
  19. 写给喜欢数学和不喜欢数学的朋友们
  20. SSD固态硬盘优化教程

热门文章

  1. 思科ccie网络工程师一定要里了解的网络拥塞及拥塞控制技术
  2. 计算机中信息的表示与存储教案,计算机基础教案2--1.2信息的表示与存储.doc
  3. 关于Beyond Compare 4秘钥过期处理方法,百试不爽
  4. 小程序 mathjs渲染公式_地平线:黎明时分中的云渲染技术
  5. mac安装配置zsh
  6. 基于Attention_CNN_GRU的野生动物监测图像分类
  7. 技嘉1080显卡体质测试软件,技嘉 GTX1080 Xtreme Gaming Premium Pack评测-太平洋电脑网...
  8. 在MyEclipse2016 中使用maven 部署项目到 tomcat中的步骤
  9. 【论文阅读】Paraformer工业级非自回归端到端语音识别模型
  10. 家用路由器被劫持?如何正确的分析与应对