今天开始学习哈希表有关知识和题目,分别是LeetCode.242有效的字母异位词和LeetCode.349两个数组的交集。
LeetCode.242有效的字母异位词


本题题目简短,看似懂很简单,但是思考起来还是比较复杂。因为之前虽然在数据结构中学过哈希表,但是并没有练习过相关算法题,思考中遇到一些问题。比如,除了两层循环暴力破解以外,一定还有更高效更便捷的办法,可是靠自己并不能想到。如果用两层循环暴力破解之后,我只能确保两个词使用的字母相同,但无法确保使用所有原字母一次。这是我在第一遍自己思考时碰到的两个典型问题。之后去听了代码随想录的讲解,了解到哈希表的数组法解题,顿感奇妙。
public static boolean isAnagram(String s,String t){
if (s.length()!=t.length()){
return false;
}
int[] nums=new int[26];
for (int i = 0; i < s.length(); i++) {
nums[s.charAt(i)%26]++;
nums[t.charAt(i)%26]--;
}
for (int i = 0; i < nums.length; i++) {
if (nums[i]!=0){
return false;
}
}
return true;
}
这道题使用哈希表的数组法的大体思路是:一个单词一共是由26个字母中的字母组成。所以我们可以创建一个长度为26的数组,数组的每一个位置分别代表一个字母,遍历第一个字符串中的字符,将数组对应下标的元素作为该字符出现的次数,例如,数组下标为0的元素代表字符a,如果a在该单词中出现3次,则该下标位置的元素设置为3,也就是arr[0]=3;。之后再去遍历第二个字符串,将每一个字符出现的次数减去。最后再遍历这个长度为26的数组,如果有某一个元素的值不为0,则说明两个字符串不是异位词。
在这个过程中,有两处处细节需要注意。第一,我们可以使用两次for循环分别遍历第一个和第二个字符串,也可以使用一个for循环同时遍历两个字符串。但是同时遍历时,为了防止两个字符串的长度不一致而导致遍历不完全或者数组越界,我们可以在前面判断其长度是否相等,如果不相等,他们肯定不是异位词,则可以直接返回false。第二,26个字母在ASCII码表上对应的数字并不是从0-25,所以我们可以通过一些方法,让他们存储到对应下标的数组元素中。第一种方法是所示代码中的,利用取模操作,完成对每一个字母的对应。第二种方法是,将对应字符减去字符 ‘a’ ,如字母f,可以使用'f'-'a'来找到对应下标。
LeetCode.349两个数组的交集

在这道题中,题目规定输出结果中的每个元素是唯一的,如示例1中,有两个2相交,但输出时只输出一个2。对于这种题目,我们可以考虑使用哈希表的set方法。但是这道题也可以使用数组法。
public static int[] intersection(int[] nums1,int[] nums2){
int[] nums=new int[1005];
for (int i = 0; i < nums1.length; i++) {
nums[nums1[i]]=1;
}
Set<Integer> set=new HashSet<>();
for (int i = 0; i < nums2.length; i++) {
if (nums[nums2[i]]==1){
set.add(nums2[i]);
}
}
Integer[] re=new Integer[set.size()];
set.toArray(re);
return Arrays.stream(re).mapToInt(Integer::valueOf).toArray();
}
862

被折叠的 条评论
为什么被折叠?



