【LeetCode 面试经典150题】详细题解之哈希表篇
【LeetCode 面试经典150题】详细题解之哈希表篇
- 1 哈希表的基础
- 1.1 基础概念及实现
- 1.2.1 哈希表的工作原理
- 1.2.2 705.设计哈希集合
- 1.2.3 706.设计哈希映射
- 1.2 HashMap相关
- 1.2.1 基本操作
- 1.2.2 遍历
- 1.3 Hashtable
- 1.4 LinkedHashMap
- 1.5 HashSet
- **1.5.1基本特性**
- 1.5.2 基本方法
- 1.5.3 注意事项
- 2 383.赎金信
- 2.1 思路
- 2.2 代码
- 3 205.同构字符串
- 3.1 思路
- 3.2 代码
- 4 290.单词规律
- 4.1 分析
- 4.2 代码
- 5 242.有效的字母异位词
- 5.1 思路
- 5.2 代码
- 6 49. 字母异位词分组
- 6.1 思路
- 6.2 代码
- 7 1.两数之和
- 7.1 思路
- 7.2 代码
- 8 202.快乐数 (需要复习)
- 8.1 思路
- 8.2 代码
- 9 219.存在重复元素II
- 9.1 思路
- 9.2 代码
- 10 128.最长连续序列
- 10.1 思路
- 10.2 代码
1 哈希表的基础
12.23 一刷
哈希表是一种基于哈希算法实现的键值对集合,提供了快速的数据插入、删除和查找功能。Java提供了HashMap
、Hashtable
和LinkedHashMap
等实现哈希表的类。以下是Java哈希表的一些基础概念和操作:
1.1 基础概念及实现
1.2.1 哈希表的工作原理
哈希表通过哈希函数将键(Key)映射到哈希表的索引上,然后通过这个索引来访问值(Value)。如果两个键的哈希值相同(哈希冲突),则通过链表或其他方法来解决冲突。
1.2.2 705.设计哈希集合
705. 设计哈希集合
不使用任何内建的哈希表库设计一个哈希集合(HashSet)。
实现 MyHashSet
类:
void add(key)
向哈希集合中插入值key
。bool contains(key)
返回哈希集合中是否存在这个值key
。void remove(key)
将给定值key
从哈希集合中删除。如果哈希集合中没有这个值,什么也不做。
class MyHashSet {/**hash函数用于将key映射到数组中用链表法来解决哈希冲突,当两个不同的数映射到数组的同一位置时,将该数接到数组位置的链表后面*///定义hash表的长度为769private static final int BASE = 769;private LinkedList[] list;public MyHashSet() {//初始化哈希表list = new LinkedList[BASE]; //初始化LinkedListfor(int i = 0;i<BASE;i++){list[i] = new LinkedList<Integer>();}}public void add(int key) {int h = hash(key);//找到key映射到hash表中的位置Iterator<Integer> iter = list[h].iterator();while(iter.hasNext()){Integer element = iter.next();if(element == key){return;}}list[h].offerLast(key);}public void remove(int key) {int h = hash(key);Iterator<Integer> iter = list[h].iterator();while(iter.hasNext()){Integer element = iter.next();if(element == key){list[h].remove(element);return;}}}public boolean contains(int key) {int h = hash(key);Iterator<Integer> iter = list[h].iterator();while(iter.hasNext()){int element = iter.next();if(element == key){return true;}}return false;}private static int hash(int key){return key % BASE;}
}/*** Your MyHashSet object will be instantiated and called as such:* MyHashSet obj = new MyHashSet();* obj.add(key);* obj.remove(key);* boolean param_3 = obj.contains(key);*/
1.2.3 706.设计哈希映射
706. 设计哈希映射
已解答
不使用任何内建的哈希表库设计一个哈希映射(HashMap)。
实现 MyHashMap
类:
MyHashMap()
用空映射初始化对象void put(int key, int value)
向 HashMap 插入一个键值对(key, value)
。如果key
已经存在于映射中,则更新其对应的值value
。int get(int key)
返回特定的key
所映射的value
;如果映射中不包含key
的映射,返回-1
。void remove(key)
如果映射中存在key
的映射,则移除key
和它所对应的value
。
class MyHashMap {/**感觉和上一个哈希表的题差不多,根据key映射到哈希表数组中的位置。只是此时,哈希表中的每个元素都应该后面还跟着value,不再是Integer了?*///定义一个Pairprivate class Pair{private int key;private int value;public Pair(int key,int value){this.key = key;this.value = value;}public int getKey(){return key;}public int getValue(){return value;}public void setValue(int value){this.value = value;}}private static final int BASE = 769;LinkedList[] list ;public MyHashMap() {list = new LinkedList[BASE];for(int i = 0;i<BASE;i++){list[i] = new LinkedList<Pair>();}}public void put(int key, int value) {int h = hash(key);Iterator<Pair> iter = list[h].iterator();while(iter.hasNext()){Pair pair = iter.next();if(pair.getKey()==key){pair.setValue(value);return;}}list[h].offerLast(new Pair(key,value));}public int get(int key) {int h = hash(key);Iterator<Pair> iter = list[h].iterator();while(iter.hasNext()){Pair pair = iter.next();if(pair.getKey()==key){return pair.getValue();}}return -1;}public void remove(int key) {int h = hash(key);Iterator<Pair> iter = list[h].iterator();while(iter.hasNext()){Pair pair = iter.next();if(pair.getKey()==key){list[h].remove(pair);return;}}}private int hash(int key){return key % BASE;}
}/*** Your MyHashMap object will be instantiated and called as such:* MyHashMap obj = new MyHashMap();* obj.put(key,value);* int param_2 = obj.get(key);* obj.remove(key);*/
1.2 HashMap相关
HashMap
是Java中使用最广泛的哈希表实现,它基于Map接口,允许键值对中的键(Key)和值(Value)为null,并且不保证映射的顺序。
HashMap<String, Integer> map = new HashMap<>();
map.put("key1", 1);
map.put("key2", 2);
Integer value = map.get("key1"); // 返回1
map.remove("key2");
1.2.1 基本操作
- put(K key, V value):将指定的值与此映射中的指定键关联。
- get(Object key):返回指定键所映射的值。
- remove(Object key):如果存在一个键的映射关系,则将其从映射中移除。
- keySet():返回映射中包含的键的Set视图。
- values():返回映射中包含的值的Collection视图。
- entrySet():返回映射中包含的键值映射关系的Set视图
1.2.2 遍历
- 使用
entrySet()
entrySet()
方法返回哈希表中所有键值对的 Set
视图。这个集合中的每个元素都是一个 Map.Entry
对象,其中包含键和值。
HashMap<String, Integer> map = new HashMap<>();
map.put("key1", 1);
map.put("key2", 2);
map.put("key3", 3);for (Map.Entry<String, Integer> entry : map.entrySet()) {String key = entry.getKey();Integer value = entry.getValue();System.out.println(key + " => " + value);
}
- 使用
keySet()
keySet()
方法返回哈希表中所有键的 Set
视图。通过这个集合遍历所有的键,然后使用每个键来获取对应的值。
for (String key : map.keySet()) {Integer value = map.get(key);System.out.println(key + " => " + value);
}
- 使用
values()
如果你只对值感兴趣,可以使用 values()
方法获取哈希表中所有值的 Collection
视图。
for (Integer value : map.values()) {System.out.println(value);
}
- 使用
forEach
增强型 for 循环(Java 8+)
Java 8 引入了 forEach
方法,它允许使用增强型 for 循环的语法来遍历 Collection
。
map.forEach((key, value) -> System.out.println(key + " => " + value));
- 使用迭代器
Iterator
使用迭代器 Iterator
来遍历哈希表可以避免在遍历时修改集合导致的 ConcurrentModificationException
。
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {Map.Entry<String, Integer> entry = iterator.next();System.out.println(entry.getKey() + " => " + entry.getValue());
}
注意事项
- 当遍历哈希表时,如果需要修改哈希表(增加或删除元素),推荐使用迭代器
Iterator
的remove
方法,或者在外部使用removeIf
方法。 entrySet()
、keySet()
和values()
返回的视图反映了哈希表的当前状态,如果哈希表被修改,视图也会相应地变化。- 遍历哈希表的时间复杂度是 O(n),其中 n 是哈希表中的元素数量。
1.3 Hashtable
Hashtable
是遗留类,也实现了Map接口,但它是同步的,不允许键或值为null,并且它的性能通常不如HashMap
。
Hashtable<String, Integer> htable = new Hashtable<>();
htable.put("key1", 1);
htable.put("key2", 2);
Integer value = htable.get("key1"); // 返回1
htable.remove("key2");
1.4 LinkedHashMap
LinkedHashMap
是HashMap
的一个子类,它维护了元素的插入顺序或者访问顺序,取决于构造函数的参数。
LinkedHashMap<String, Integer> lmap = new LinkedHashMap<>();
lmap.put("key1", 1);
lmap.put("key2", 2);
Integer value = lmap.get("key1"); // 返回1
lmap.remove("key2");
1.5 HashSet
HashSet
是 Java 中的一个集合类,它实现了 Set
接口,不允许集合中有重复的元素。HashSet
的行为是由 HashMap
实现的,它使用哈希表来存储元素,因此具有很高的添加、删除和搜索效率。以下是 HashSet
的一些基础知识和遍历方法:
1.5.1基本特性
- 不允许重复:
HashSet
不允许存储重复元素。 - 无序:
HashSet
中的元素是无序的,这意味着元素插入和取出的顺序不一定相同。 - 非线程安全:
HashSet
是非线程安全的,如果需要线程安全,可以使用Collections.synchronizedSet
或CopyOnWriteArraySet
。
1.5.2 基本方法
// 创建
HashSet<String> set = new HashSet<>();
//添加
set.add("element1");
set.add("element2");
//删除
boolean removed = set.remove("element1"); // 返回 true 如果元素被移除,false 如果元素不存在// 判断元素是否存在
boolean contains = set.contains("element1"); // 返回 true 如果元素存在,false 否则// 遍历1
for (String element : set) {System.out.println(element);
}// 遍历2
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {String element = iterator.next();System.out.println(element);
}// 遍历3
set.forEach(element -> System.out.println(element));// 遍历4
set.stream().forEach(System.out::println);
1.5.3 注意事项
HashSet
中的元素顺序不可预测,如果你需要有序的集合,可以考虑使用TreeSet
。- 由于
HashSet
依赖于哈希函数,某些情况下可能会遇到哈希冲突,但 Java 的实现已经足够高效,冲突通常不会影响性能。 - 当遍历或迭代
HashSet
时,如果需要修改集合,应该使用迭代器的remove
方法,或者在外部使用removeIf
方法。
2 383.赎金信
383. 赎金信
简单
给你两个字符串:ransomNote
和 magazine
,判断 ransomNote
能不能由 magazine
里面的字符构成。
如果可以,返回 true
;否则返回 false
。
magazine
中的每个字符只能在 ransomNote
中使用一次。
示例 1:
输入:ransomNote = "a", magazine = "b"
输出:false
示例 2:
输入:ransomNote = "aa", magazine = "ab"
输出:false
示例 3:
输入:ransomNote = "aa", magazine = "aab"
输出:true
提示:
1 <= ransomNote.length, magazine.length <= 105
ransomNote
和magazine
由小写英文字母组成
2.1 思路
简单字符可以用长度为26的数组来记录字符出现的次数
两个哈希表记录ransomNote和magazin两个字符串中,字符出现的次数,之后再一一比较由于是简单的字符,所以可以用两个长度为26的数组来记录字符出现的次数cnt_r[26]cnt_m[26]之后遍历cnt_r中的值,判断cnt_r中的每个字符出现的数量是否大于cnt_m中该字符出现的数量。小于则直接返回false
2.2 代码
class Solution {public boolean canConstruct(String ransomNote, String magazine) {/***/int[] cnt_r = new int[26];int[] cnt_m = new int[26];for(int i = 0;i<ransomNote.length();i++){cnt_r[ransomNote.charAt(i)-'a']++;}for(int i = 0;i<magazine.length();i++){cnt_m[magazine.charAt(i)-'a']++;}for(int i = 0;i<26;i++){if(cnt_r[i]>cnt_m[i]){return false;}}return true;}
}
3 205.同构字符串
205. 同构字符串
简单
给定两个字符串 s
和 t
,判断它们是否是同构的。
如果 s
中的字符可以按某种映射关系替换得到 t
,那么这两个字符串是同构的。
每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。
示例 1:
输入:s = "egg", t = "add"
输出:true
示例 2:
输入:s = "foo", t = "bar"
输出:false
示例 3:
输入:s = "paper", t = "title"
输出:true
提示:
1 <= s.length <= 5 * 104
t.length == s.length
s
和t
由任意有效的 ASCII 字符组成
3.1 思路
第一遍的时候用1个hashmap,这样会存在s->t一对一,t->s多对多的问题
两个HashMap,分别存储s-> t的映射和t-> s的映射
用一个HashMap存储s中字符到t的映射关系,之后判断即可具体而言,对于s和t,假如是同构的,那么s中的所有字符都能映射到t中。即map[s[i]] = t[i] 会对所有的i都满足。反之,假如不满足上面条件,则说明不同构。举例s = egg,t = add遍历s和t中的每个元素,在第一个元素的时候,得出映射关系为 e->a第二个元素 g->d第三个元素 g->d,成立。具体实现则是,维持两个HashMap,分别存储s->t的映射和t->s的映射。因为一个的话会存在这种情况。s = bacdt = baba对于s中的字符满足唯一映射,但是对于t中的,比如b会映射到{b,c}不对。因此,维持两个map,s2t中以s字符为键,映射至t的字符为值t2s中以t字符为键,映射至s的字符为值从左到右遍历两个字符串,更新哈希表。出现冲突时(当前下标i对应的s[i]存在映射,但是映射不为t[i],或者t[i]存在映射,但是映射不为s[i])返回false
3.2 代码
class Solution {public boolean isIsomorphic(String s, String t) {/***/int n = s.length();Map<Character,Character> maps2t = new HashMap<>();Map<Character,Character> mapt2s = new HashMap<>();for(int i = 0;i<n;i++){char si = s.charAt(i);char ti = t.charAt(i);//冲突if(maps2t.containsKey(si) && maps2t.get(si) != ti){return false;}if(mapt2s.containsKey(ti) && mapt2s.get(ti) != si){return false;}maps2t.put(s.charAt(i),t.charAt(i));mapt2s.put(t.charAt(i),s.charAt(i));}return true;}
}
4 290.单词规律
290. 单词规律
简单
给定一种规律 pattern
和一个字符串 s
,判断 s
是否遵循相同的规律。
这里的 遵循 指完全匹配,例如, pattern
里的每个字母和字符串 s
中的每个非空单词之间存在着双向连接的对应规律。
示例1:
输入: pattern = "abba", s = "dog cat cat dog"
输出: true
示例 2:
输入:pattern = "abba", s = "dog cat cat fish"
输出: false
示例 3:
输入: pattern = "aaaa", s = "dog cat cat dog"
输出: false
提示:
1 <= pattern.length <= 300
pattern
只包含小写英文字母1 <= s.length <= 3000
s
只包含小写英文字母和' '
s
不包含 任何前导或尾随对空格s
中每个单词都被 单个空格 分隔
4.1 分析
和205.同构字符串差不多的题。简单题
4.2 代码
class Solution {public boolean wordPattern(String pattern, String s) {/**感觉和上一题一样,都是维护两个map,然后双向映射。思路差不多。*/String[] strs = s.split(" ");if(strs.length!=pattern.length()){return false;}Map<Character,String> c2strs = new HashMap<>();Map<String,Character> strs2c = new HashMap<>();for(int i = 0;i<strs.length;i++){char c = pattern.charAt(i);if(c2strs.containsKey(c) && !c2strs.get(c).equals(strs[i])){return false;}if(strs2c.containsKey(strs[i]) && strs2c.get(strs[i])!=c ){return false;}c2strs.put(c,strs[i]);strs2c.put(strs[i],c);}return true;}
}
5 242.有效的字母异位词
242. 有效的字母异位词
简单
给定两个字符串 s
和 t
,编写一个函数来判断 t
是否是 s
的 字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram"
输出: true
示例 2:
输入: s = "rat", t = "car"
输出: false
提示:
1 <= s.length, t.length <= 5 * 104
s
和t
仅包含小写字母
进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?
5.1 思路
分析,不难
一个cnt数组1.将s中所有出现过的字母放入cnt中记录2.遍历t,遇见一个t的字母,就在cnt中减去对应的值。假如减之后cnt值<0,则s和t的字符一定不相同。返回false3.遍历cnt,假如有不为0的数,返回false
5.2 代码
class Solution {public boolean isAnagram(String s, String t) {/***/if(s.length()!=t.length()){return false;}int[] cnt = new int[26];for(char c: s.toCharArray()){cnt[c-'a']++;}for(char c: t.toCharArray()){cnt[c-'a']--;if(cnt[c-'a']<0){return false;}}return true;}
}
6 49. 字母异位词分组
49. 字母异位词分组
中等
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
示例 1:
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
示例 2:
输入: strs = [""]
输出: [[""]]
示例 3:
输入: strs = ["a"]
输出: [["a"]]
提示:
1 <= strs.length <= 104
0 <= strs[i].length <= 100
strs[i]
仅包含小写字母
6.1 思路
重点是用Arrays.sort排序?排序后的字符串作为key
遍历strs,对strs中的每个str,先使用Arrays.sort排序,维持一个<String,List<String>> 的Map,排序后的字符串作为Key,排序前的作为Value最后,遍历Map,取出Map中的所有Value放到List结果中
6.2 代码
class Solution {public List<List<String>> groupAnagrams(String[] strs) {/***/Map<String,List<String>> map = new HashMap<>();for(String str:strs){char[] str_c = str.toCharArray();Arrays.sort(str_c);String key = new String(str_c);List<String> list = map.getOrDefault(key,new ArrayList<String>());list.add(str);map.put(key,list);}List<List<String>> res = new ArrayList<>();for(Map.Entry<String,List<String>> entry: map.entrySet()){res.add(entry.getValue());}return res;}
}
7 1.两数之和
1. 两数之和
简单
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
- 只会存在一个有效答案
**进阶:**你可以想出一个时间复杂度小于 O(n2)
的算法吗?
7.1 思路
经典题目,但是第一遍只想得起来暴力
- 暴力枚举遍历
- 用Map记录数字和他的下标。之后遍历的时候就能通过hashmap知道target-x是否出现过了。
枚举遍历要加速的话可以用空间换时间,用一个Map记录每个数字和他的下标。之后给原数组排序。然后双指针遍历。上面是一个思路。实际上是记录了之后,在遍历的时候能够借助hashmap知道target-x是否出现过。因此时间复杂度能从O(n^2)降到O(1)// int n = nums.length;// for(int i = 0;i<n;i++){// for(int j = i+1;j<n;j++){// if(nums[i]+nums[j]==target){// return new int[]{i,j};// }// }// }// return new int[]{};
7.2 代码
class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer,Integer> map = new HashMap<>();for(int i = 0;i<nums.length;i++){if(map.containsKey(target-nums[i])){return new int[]{i,map.get(target-nums[i])};}map.put(nums[i],i);}return new int[]{};}
}
8 202.快乐数 (需要复习)
202. 快乐数
简单
编写一个算法来判断一个数 n
是不是快乐数。
「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n
是 快乐数 就返回 true
;不是,则返回 false
。
示例 1:
输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
示例 2:
输入:n = 2
输出:false
提示:
1 <= n <= 231 - 1
8.1 思路
可以用哈希表做,用哈希表记录出现的数字,当出现重复的时候就可以返回了。
如果重复的数字为1,说明是快乐数,否则不为快乐数。
巧妙的是快慢指针判断有环的解法。具体参考下面
快慢指针快指针每次走2步,慢指针每次走1步,二者相等时,即为1个循环周期若有环则一定能相遇,若无环也会相遇,但相遇点为1想起来了那道判断链表进环点的题。也是快慢指针。相遇后,让一个新的指针从起点开始,以和慢指针一样的速度行动,相遇的节点即为入环点。但是本题只用判断循环点是否为1即可。
8.2 代码
class Solution {public boolean isHappy(int n) {/***/int slow = n,fast = n;do{slow = bigSquareSum(slow);fast = bigSquareSum(fast);fast = bigSquareSum(fast);}while(slow != fast);if(slow==1){return true;}return false;}int bigSquareSum(int n){int sum = 0;while(n!=0){sum+= (n%10)*(n%10);n=n/10;}return sum;}
}
9 219.存在重复元素II
219. 存在重复元素 II
已解答
简单
给你一个整数数组 nums
和一个整数 k
,判断数组中是否存在两个 不同的索引 i
和 j
,满足 nums[i] == nums[j]
且 abs(i - j) <= k
。如果存在,返回 true
;否则,返回 false
。
示例 1:
输入:nums = [1,2,3,1], k = 3
输出:true
示例 2:
输入:nums = [1,0,1,1], k = 1
输出:true
示例 3:
输入:nums = [1,2,3,1,2,3], k = 2
输出:false
提示:
1 <= nums.length <= 105
-109 <= nums[i] <= 109
0 <= k <= 105
9.1 思路
hashmap的应用
维护一个HashMap,map中是nums中的值->下标的映射遍历nums,假如在遍历时发现map中存储过该值,则根据map取出上次出现的下标,计算是否满足i-j<=k,若不满足,则将当前下标更新为j
9.2 代码
class Solution {public boolean containsNearbyDuplicate(int[] nums, int k) {/***/Map<Integer,Integer> map = new HashMap<>();for(int i=0;i<nums.length;i++){int num = nums[i];if(map.containsKey(num)){if(i-map.get(num)<=k){return true;}}map.put(num,i);}return false;}
}
10 128.最长连续序列
给定一个未排序的整数数组 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 <= 105
-109 <= nums[i] <= 109
10.1 思路
具体如下。重点是
- 需要找到可能的连续序列 开始的数字,之后往后遍历计算最长连续序列即可。
利用hash表来存储nums的值,帮助枚举连续的数1.先遍历nums,将nums中的值都存在hashset中2.遍历hashset,找到每个可能的连续序列开始的数,然后从该数开始往后遍历,计算最长连续序列
10.2 代码
class Solution {public int longestConsecutive(int[] nums) {/***/Set<Integer> set = new HashSet<>();for(Integer num: nums){set.add(num);}int res = 0;for(Integer num: set){//2.1 判断是不是连续序列最开始的数if(set.contains(num-1)){continue;}//2.2 说明是连续序列最开始的数int curres = 0;while(set.contains(num++)){curres++;}res = Math.max(res,curres);}return res;}
}
相关文章:
【LeetCode 面试经典150题】详细题解之哈希表篇
【LeetCode 面试经典150题】详细题解之哈希表篇 1 哈希表的基础1.1 基础概念及实现1.2.1 哈希表的工作原理1.2.2 705.设计哈希集合1.2.3 706.设计哈希映射 1.2 HashMap相关1.2.1 基本操作1.2.2 遍历 1.3 Hashtable1.4 LinkedHashMap1.5 HashSet**1.5.1基本特性**1.5.2 基本方法…...

linux socket编程之udp_dict_serve服务端--引入配置文件
注意:本篇博客只是对上一篇博客功能的增加 1.创建配置文件(翻译) Dict.txt apple: 苹果 banana: 香蕉 cat: 猫 dog: 狗 book: 书 pen: 笔 happy: 快乐的 sad: 悲伤的 run: 跑 jump: 跳 teacher: 老师 student: 学生 car: 汽车 bus: 公交车 love: 爱 hate: 恨 hell…...
selenium学习笔记(二)
文章目录 前言设计模式POMPOM概念POM优势POM设计原则POM的实现 selenium的常用操作处理动态元素截图操作勾选复选框多层框架/窗口定位操作下拉框上传文件操作处理弹窗切换窗口拖拽操作 如何处理浏览器驱动更新导致的问题selenium与网站监控监听网页内容变化监控网络请求 seleni…...

宏集eX710物联网工控屏在石油开采机械中的应用与优势
案例概况 客户:天津某石油机械公司 应用产品:宏集eX710物联网工控屏 应用场景:钻井平台设备控制系统 一、应用背景 石油开采和生产过程复杂,涵盖钻井平台、采油设备、压缩机、分离器、管道输送系统等多种机械设备。这些设备通…...
linux——vi命令常用操作
一、vi模式 vi一般分为三种模式,分别是命令行模式、插入模式、末行模式 1.命令模式:控制屏幕光标的移动,按 :进入末行模式,按 i(其他插入命令也可) 进入插入模式; 2.插入模式&…...

vscode添加全局宏定义
利用vscode编辑代码时,设置了禁用非活动区域着色后,在一些编译脚本中配置的宏又识别不了 遇到#ifdef包住的代码就会变暗色,想查看代码不是很方便。如下图: 一 解决: 在vscode中添加全局宏定义。 二 步骤:…...
重装荣耀X14笔记本电脑踩坑记
这几天趁着有国补搞了台荣耀 X14笔记本电脑。到手后第一件事情对我来说当然是要重装成Windows 11 LTSC版。所以按以往的经验做了个USB启动安装盘,但发现上电后按F12能进入启动设备选择,可是USB分类下没有任何设备。重启按F2进入设置界面,关闭…...
Android `android.graphics.drawable` 包深度解析:架构与设计模式
Android android.graphics.drawable 包深度解析:架构与设计模式 目录 引言Drawable 概述Drawable 的架构 Drawable 类层次结构Drawable 的核心方法Drawable 的设计模式 装饰者模式工厂模式状态模式常用 Drawable 子类解析 BitmapDrawableShapeDrawableLayerDrawableStateList…...
Kotlin语言的软件工程
Kotlin语言的软件工程 引言 在现代软件开发中,选择合适的编程语言是项目成功的关键之一。随着移动互联网的迅猛发展,以及大数据和人工智能等新兴技术的崛起,Kotlin语言凭借其简洁、高效和安全等特性,迅速崛起为备受欢迎的编程语…...
面试经典 150 题——数组/字符串(一)
文章目录 1、合并两个有序数组1.1 题目链接1.2 题目描述1.3 解题代码1.4 解题思路 2、移除元素2.1 题目链接2.2 题目描述2.3 解题代码2.4 解题思路 3、删除有序数组中的重复项3.1 题目链接3.2 题目描述3.3 解题代码3.4 解题思路 4、删除有序数组中的重复项 II4.1 题目链接4.2 题…...

使用亚马逊针对 PyTorch 和 MinIO 的 S3 连接器实现可迭代式数据集
2023 年 11 月,Amazon 宣布推出适用于 PyTorch 的 S3 连接器。适用于 PyTorch 的 Amazon S3 连接器提供了专为 S3 对象存储构建的 PyTorch 数据集基元(数据集和数据加载器)的实现。它支持用于随机数据访问模式的地图样式数据集和用于流式处理…...

TestMAX/DFT Compiler:时序单元的类型、连接顺序和后DFT优化
相关阅读 TestMAX/DFT Compilerhttps://blog.csdn.net/weixin_45791458/category_12865937.html?spm1001.2014.3001.5482 时序单元的状态 未映射的时序单元(Unmapped Sequential Cell) 在Design Compiler读取了一个RTL设计后,Design Compiler内置的HDL Compiler工…...

CAN201 Introduction to Networking(计算机网络)Pt.3 网络层
文章目录 4.Network Layter(网络层)4.1 Overview4.2 Router(路由器)4.3 Internet Protocol4.4 IPv4 addressing4.5 NAT(network address translation,网路地址转换)4.6 IPv64.7 Generalized For…...

App Factory:简化和加速私人应用开发
App Factory是Codigger提供的一套先进的开发工具、库和API,旨在帮助开发人员在现有的软件基础上添加特定的功能或扩展。它为私人应用的创建、开发和发布提供了一整套先进的工具集、集成的相关资源库以及强大的API接口,使开发者能够在现有的Codigger架构之…...

PHP语言laravel框架中基于Redis的异步队列使用实践与原理
在 Laravel 中,基于 Redis 的异步队列是通过 Laravel 的队列系统与 Redis 服务结合来实现的。这种队列机制允许你将任务推送到队列中,并由后台工作进程异步处理这些任务。这样,你就可以将耗时的操作(如发送邮件、处理视频、数据同…...

全面Kafka监控方案:从配置到指标
文章目录 1.1.监控配置1.2.监控工具1.3.性能指标系统相关指标GC相关指标JVM相关指标Topic相关指标Broker相关指标 1.4.性能指标说明1.5.重要指标说明 1.1.监控配置 开启JMX服务端口:kafka基本分为broker、producer、consumer三个子项,每一项的启动都需要…...

kipotix4靶机实战
信息收集 1.判断靶机ip 原理:开靶机之前nmap扫一次网段,再开靶机之后扫一次,查看多出来的ip就是靶机ip ip192.168.98.1742.判断端口服务,系统版本 a.确定端口 b.-p指定端口进一步收集 c.信息筛选 1.端口:22,80,139,…...

我的秋招总结
我的秋招总结 个人背景 双非本,985硕,科班 准备情况 以求职为目的学习Java的时间大概一年。 八股,一开始主要是看B站黑马的八股文课程,背JavaGuide和小林coding还有面试鸭。 算法,250,刷了3遍左右 项目&…...

广义线性模型(GLM)全面解析
引言 广义线性模型(Generalized Linear Model, GLM)是统计学中一种重要的建模工具,它扩展了传统线性回归模型,能够处理响应变量的非正态分布和非线性关系。GLM 的灵活性和广泛的应用范围使其在金融、医学、社会科学等领域中成为数…...

C++ OCR 文字识别
一.引言 文字识别,也称为光学字符识别(Optical Character Recognition, OCR),是一种将不同形式的文档(如扫描的纸质文档、PDF文件或数字相机拍摄的图片)中的文字转换成可编辑和可搜索的数据的技术。随着技…...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...