文章目录
- 哈希表
- 1. 两数之和
- 面试题 01.02. 判定是否互为字符重排
- 217. 存在重复元素
- 219. 存在重复元素 II
- 49. 字母异位词分组
哈希表
哈希表是什么:存储数据的容器
作用:快速查找某个元素。O(1)
当我们需要频繁的查找某一个数的时候,可以使用哈希表。
如何用哈希表:
- 容器(哈希表)
- 用数组模拟简易哈希表
(字符串中的“字符”)
(数据范围很小的时候)
1. 两数之和
题目链接: leetcode1. 两数之和
解法一:暴力解法
- 先固定其中一个数
- 依次与该数之前的数相加
代码:
class Solution {public int[] twoSum(int[] nums, int target) {int[] ret = new int[2];for (int i = 0; i < nums.length; i++) {for (int j = i - 1; j >= 0; j--) {if (nums[i] + nums[j] == target) {ret[0] = i;ret[1] = j;return ret;}}}return ret;}
}
twoSum
该方法接收两个参数:一个整数数组nums
和一个整数target
。方法的目的是在nums
数组中找到两个数,使它们的和等于target,并返回这两个数的索引。
解析:
- 创建一个长度为2的整数数组
ret
,用于存储找到的两个数的索引。 - 使用两层
for
循环遍历nums
数组。外层循环遍历数组中的每个元素,内层循环从当前元素的前一个元素开始向前遍历。 - 如果在内层循环中找到两个数的和等于
target
,将它们的索引分别存储在ret
数组的第0个和第1个位置,并返回ret
数组。 - 如果遍历完整个数组都没有找到满足条件的两个数,返回
ret
数组(此时ret
数组中的元素未被修改)。
解法二:哈希表
class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer,Integer> hash = new HashMap<>();for(int i = 0; i < nums.length;i++){int x = target - nums[i];if(hash.containsKey(x)){return new int[]{i,hash.get(x)};}hash.put(nums[i],i);}return new int[]{-1,-1};}
}
twoSum
该方法接收两个参数:一个整数数组nums
和一个整数target
。方法的目的是在nums
数组中找到两个数,使它们的和等于target
,并返回这两个数的索引。
首先,创建一个HashMap
(名为hash
)来存储数组中的元素及其对应的索引。然后,遍历数组nums
,对于每个元素nums[i]
,计算target
减去nums[i]
的值(x)。接着,检查hash中是否包含键x。如果包含,说明找到了两个数的和等于target
,返回这两个数的索引(i和hash.get(x))
。如果不包含,将当前元素nums[i]
及其索引i
添加到hash
中。
如果遍历完数组后仍未找到满足条件的两个数,返回一个包含两个-1的数组。
面试题 01.02. 判定是否互为字符重排
题目链接: 面试题 01.02. 判定是否互为字符重排
CheckPermutation
该方法接受两个字符串参数s1
和s2
,并返回一个布尔值。
方法的功能是检查两个字符串是否为彼此的排列(permutation)。它首先检查两个字符串的长度是否相等,如果不相等则直接返回false
。然后,它创建一个长度为26的整型数组hash
,用于记录每个字符出现的次数。
接下来,通过遍历字符串s1
,将每个字符对应的位置在hash
数组中加一。然后,再遍历字符串s2
,将每个字符对应的位置在hash
数组中减一。如果在遍历过程中发现某个字符在hash
数组中的值小于零,说明该字符在s2
中出现的次数超过了在s1
中出现的次数,因此返回false
。
如果遍历完两个字符串后没有发现任何问题,说明两个字符串是彼此的排列,返回true
。
以下是代码的解析:
class Solution {public boolean CheckPermutation(String s1, String s2) {if (s1.length() != s2.length()) {return false;}int[] hash = new int[26];for (int i = 0; i < s1.length(); i++) {hash[s1.charAt(i) - 'a']++;}for (int i = 0; i < s2.length(); i++) {hash[s2.charAt(i) - 'a']--;if (hash[s2.charAt(i) - 'a'] < 0) {return false;}}return true;}
}
217. 存在重复元素
题目链接: 217. 存在重复元素
class Solution {public boolean containsDuplicate(int[] nums) {Set<Integer> hash = new HashSet<>();for(int s : nums){if(hash.contains(s)){return true;}hash.add(s);}return false;}
}
containsDuplicate
该方法接受一个整数数组nums
作为参数。方法的目的是检查数组中是否存在重复的元素。
代码中使用了一个HashSet
来存储已经遍历过的元素。对于数组中的每个元素s
,首先检查HashSet
中是否已经包含了该元素。如果包含,说明存在重复元素,返回true
。如果不包含,将该元素添加到HashSet
中。
如果遍历完整个数组后都没有发现重复元素,则返回false
。
219. 存在重复元素 II
题目链接: 219. 存在重复元素 II
class Solution {public boolean containsNearbyDuplicate(int[] nums, int k) {Map<Integer,Integer> hash = new HashMap<>();for(int i = 0; i < nums.length; i++){if(hash.containsKey(nums[i])){if(i - hash.get(nums[i]) <= k){return true;}}hash.put(nums[i],i);}return false;}
}
这段代码的功能是检查一个整数数组 nums
中是否存在两个相同的元素,且这两个相同元素的索引之间的差值不超过一个给定的整数 k
。
具体来说,方法 containsNearbyDuplicate
接受两个参数:
int[] nums
: 一个整数数组。int k
: 一个非负整数,表示允许的最大索引差。
方法通过使用一个哈希表(在 Java 中是 HashMap
)来跟踪每个数字最后出现的位置。算法如下:
-
初始化一个空的
HashMap
,用于存储数组中的数字及其对应的最新索引。 -
遍历数组
nums
中的每个数字nums[i]
。 -
对于每个数字
nums[i]
,检查它是否已经在HashMap
中存在:- 如果不存在,将该数字和其索引
i
添加到HashMap
中。 - 如果存在,获取该数字之前记录的索引
lastIndex
,并计算当前索引i
与lastIndex
的差值。
- 如果不存在,将该数字和其索引
-
如果这个差值小于或等于
k
,则返回true
,表示找到了两个索引差不超过k
的相同元素。 -
如果遍历完整个数组后没有找到这样的元素对,则返回
false
。
这个方法可以用于解决一些与数组中重复元素位置有关的问题,例如在滑动窗口内查找重复项等。
49. 字母异位词分组
题目链接: 49. 字母异位词分组
-
算法概述:
- 遍历输入字符串列表。
- 对于每个字符串:
- 将其转换为字符数组。
- 对字符数组进行排序。
- 创建一个键,将排序后的字符数组转换回字符串。
- 如果该键尚不存在于映射中,则为该键创建一个新列表。
- 将原始字符串添加到与该键对应的列表中。
- 从映射中提取结果,返回值为一组同字母异序词的列表。
-
解释:
- 代码使用一个名为
hash
的Map<String, List<String>>
来存储同字母异序词。 - 对于每个输入字符串
s
:- 将
s
转换为字符数组(tmp
)。 - 对字符数组进行排序。
- 创建一个键,将排序后的字符数组转换回字符串。
- 如果该键尚不存在于映射中,则为该键创建一个新列表。
- 将
s
添加到与该键对应的列表中。
- 将
- 最后,从映射中返回值(同字母异序词的列表)。
- 代码使用一个名为
-
示例:
- 给定输入:
strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
- 输出:
[["bat"], ["nat", "tan"], ["ate", "eat", "tea"]]
- 给定输入:
-
约束条件:
- 1 <=
strs.length
<= 10^4 - 0 <=
strs[i].length
<= 100 strs[i]
由小写英文字母组成。
- 1 <=
-
判断两个字符串是否是字母异位词
-
分组
class Solution {public List<List<String>> groupAnagrams(String[] strs) {Map<String,List<String>> hash = new HashMap<>();// 1.把所有的字符异位词分组for(String s : strs){char[] tmp = s.toCharArray();Arrays.sort(tmp);String key = new String(tmp);if(!hash.containsKey(key)){hash.put(key,new ArrayList());}hash.get(key).add(s);}//2. 提取结果return new ArrayList(hash.values());}
}
代码解释:
1. 定义类和方法:
class Solution { public List<List<String>> groupAnagrams(String[] strs) {
这里定义了一个名为Solution的类,并在其中定义了一个名为groupAnagrams的公共方法,该方法接受一个字符串数组strs作为参数,并返回一个二维列表,其中每个内部列表都包含一组字符异位词。
2. 初始化哈希表:
Map<String,List<String>> hash = new HashMap<>();
使用Java的HashMap数据结构来存储分组。其中键(key)是排序后的字符串,值(value)是一个列表,包含所有与该键对应的原始字符串(即字符异位词)。
3. 分组字符异位词:
for(String s : strs){ char[] tmp = s.toCharArray(); Arrays.sort(tmp); String key = new String(tmp); if(!hash.containsKey(key)){ hash.put(key,new ArrayList()); } hash.get(key).add(s);
}
对于strs数组中的每个字符串s:
- 首先,将字符串转换为字符数组
tmp
。 - 然后,对字符数组进行排序,以消除字符顺序的影响。
- 接着,将排序后的字符数组转换回字符串,作为哈希表的键(key)。
- 如果哈希表中还没有这个键,则创建一个新的空列表作为值,并将其添加到哈希表中。
- 最后,将原始字符串
s
添加到与该键对应的列表中。
4. 提取结果:
return new ArrayList(hash.values());
将哈希表中的所有值(即所有字符异位词的列表)提取出来,并放入一个新的列表中。这个新列表就是最终的结果,它包含了所有分组后的字符异位词。