前言
哈希表理论知识点总结:
- 暂未总结
一、242题(有效的字母异位词)
题目描述:
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
示例 1: 输入: s = “anagram”, t = “nagaram” 输出: true
示例 2: 输入: s = “rat”, t = “car” 输出: false
说明: 你可以假设字符串只包含小写字母。
题解
mine:击败82.81%的用户。看了一下都是这个解法
class Solution {
public boolean isAnagram(String s, String t) {
int[] nums = new int[26];
int i=0;
if(s.length()!=t.length()) return false;
while(i<s.length()){
nums[s.charAt(i)-'a']++;
i++;
}
i=0;
while(i<t.length()){
nums[t.charAt(i)-'a']--;
i++;
}
for(i=0;i<26;i++){
if(nums[i]!=0){
return false;
}
}
return true;
}
}
算法思路:用nums数组记录,s里出现的元素++,t出现的元素–,如果最后nums数组全为0,就返回true。
注:①数组写法不能是int nums[26] = new int[26];//int nums[] = new int[26]②字符串长度是length()方法
基本相同题目:383(简单,不多做说明)
二、49题(字母异位词分组)
题目描述:
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
示例 1:
输入: strs = [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
输出: [[“bat”],[“nat”,“tan”],[“ate”,“eat”,“tea”]]
题解1(数组哈希)
mine:超过时间限制了,通过了111/126个测试用例
原因:这个题放在数组哈希题的后面,误导了我~~~~应该用map来求解,不然每个都比较一遍nums特别费时
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
// List<Integer.> order = new ArrayList<Integer.>();
// order.add(matrix[x][y])
List<List<String>> ans = new ArrayList<List<String>>();
int[] vis = new int[strs.length];
int i=0;
while(i<strs.length){
if(vis[i]==0){
vis[i]=1;
List<String> list = new ArrayList<String>();
list.add(strs[i]);
int nums[] = new int[26];
for(int k=0;k<strs[i].length();k++){
nums[strs[i].charAt(k)-'a']++;
}
for(int j=i+1;j<strs.length;j++){
// 先拷贝nums
int[] nums2 = nums.clone();
if(vis[j]==0&&strs[j].length()==strs[i].length()){
for(int k=0;k<strs[j].length();k++){
nums2[strs[j].charAt(k)-'a']--;
}
boolean flag=true;
for(int k=0;k<26;k++){
if(nums2[k]!=0){
flag=false;
}
}
if(flag){
vis[j]=1;
list.add(strs[j]);
}
}
}
ans.add(list);
}
i++;
}
return ans;
}
}
算法思路:一个个遍历比较,并且引入vis[]数组记录是否已经加入过list。
备注:还是基础不牢固,List的声明补充
①
List<List<String>> ans = new ArrayList<List<String>>();
//而不是List<List<String>> ans = new ArrayList<ArrayList<String>>();
②
List<String> list = new ArrayList<String>();
解法2 (map哈希)
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
HashMap<String,ArrayList> result = new HashMap<>();
for(String s:strs) {
int[] nums = new int[26];
for(char c: s.toCharArray()) {
nums[c-'a']++;
}
//由于数组是不可哈希的,我们将其转化成String(该类型可哈希)
// 因为array1[]={1,2,3}和array2[]={1,2,3}如果set.add(array1/array2)后size是2,表示这两个哈希值不同。而string1="1,2,3"
StringBuilder sb = new StringBuilder();
for(int count:count_table) {
sb.append("#");
sb.append(count);
}
String key = sb.toString();
if(!result.containsKey(key)) {
result.put(key, new ArrayList<>());
}
result.get(key).add(s);
}
return new ArrayList(result.values());
}
}
算法思路:用nums[26]记录每个字母出现的次数,由于array不可哈希,无法作为key,将其转化为String,转化方法为在每个nums[i]前添加’#',因为可能出现1,0,12和1,0,1,2相同的情况解释一下:我一开始觉得[1,0,12]和[1,0,1,2]还是可以区分的呀,那就是10120和1012。但其实是不对的,反例:[1,0,1,2,0,13,0,0]和[1,0,1,2,0,0,13,0],所以还是要用#号将数字隔开
。这样就可以将转化后的String表示的nums数组作为key,从而有了对应的value。最后values就是本题的答案。
解法3(排序法)
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
HashMap<String,ArrayList> result = new HashMap<>();
for(String s: strs) {
//sort string
char[] temp = s.toCharArray();
Arrays.sort(temp);
String key = new String(temp);
if( !result.containsKey(key)) {
result.put(key,new ArrayList<>());
}
result.get(key).add(s);
}
return new ArrayList(result.values());
}
}
算法思路:由于同一组的单词,每个经过排序后,都会变成相同的单词,所以可以把该排序后的单词作为key,寻找对应的value集合。最后输出的values即为本题答案。
三、438题(找到字符串中所有字母异位词)
题目描述:
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
题解1
mine:偷懒了,结果稀碎了..打败了5.02%的用户😀
class Solution {
public List<Integer> findAnagrams(String s, String p) {
// String sub = a.substring(index1, index2);[index1,index2)
List<Integer> list = new ArrayList<Integer>();
if(s.length()<p.length()) return list;//不是return null
int num = s.length()-p.length()+1;
String strs[] = new String[num];
for(int i=0;i<num;i++){
strs[i] = s.substring(i,i+p.length());
}
char[] chars = p.toCharArray();
Arrays.sort(chars);
String key = new String(chars);
char[] str;
String strchar;
for(int i=0;i<num;i++){
str = strs[i].toCharArray();
Arrays.sort(str);
strchar = new String(str);
if(strchar.equals(key)){
list.add(i);
}
}
return list;
}
}
算法思路:排序法。
四、349题(两个数组的交集)
题目描述:
给定两个数组 nums1 和 nums2 ,返回它们的交集。我们可以不考虑输出结果的顺序 。
题解1
import java.util.HashSet;
import java.util.Set;
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) {
return new int[0];
}
Set<Integer> set1 = new HashSet<>();
Set<Integer> resSet = new HashSet<>();
//遍历数组1
for (int i : nums1) {
set1.add(i);
}
//遍历数组2的过程中判断哈希表中是否存在该元素
for (int i : nums2) {
if (set1.contains(i)) {
resSet.add(i);
}
}
int[] arr = new int[resSet.size()];
int j = 0;
for(int i : resSet){
arr[j++] = i;
}
return arr;
}
}
注意点:①返回new int[0] ②HashSet的应用,contains()和size()和add()
③也可以用retainAll方法。
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
if (nums1.length == 0|| nums2.length == 0) {
return new int[0];
}
Set<Integer> set1 = new HashSet<>();
Set<Integer> set2 = new HashSet<>();
//遍历数组1
for (int i : nums1) {
set1.add(i);
}
for (int i : nums2) {
set2.add(i);
}
// 调用retainAll方法:会保留set1中存在于set2中的元素
// 注意该方法是操作set1,返回bool值
set1.retainAll(set2);
int[] arr = new int[set1.size()];
int j = 0;
for(int i : set1){
arr[j++] = i;
}
return arr;
}
}
注意set不能用set2=set1,这是浅拷贝。只能用set2.addAll(set1);
题解2(Hash数组法)
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
int[] hash1 = new int[1002];
int[] hash2 = new int[1002];
for(int i=0;i<nums1.length;i++){
hash1[nums1[i]]++;
}
for(int i=0;i<nums2.length;i++){
hash2[nums2[i]]++;
}
// 如果遇到hash1[i]和hash2[i]均不为0,则加入结果数组中
// 因此,如果使用固定数组,需要先判断有多个这样的,所以可以使用
// 变化数组 ArrayList
List<Integer> list = new ArrayList<>();
for(int i = 0; i < 1002; i++)
if(hash1[i] > 0 && hash2[i] > 0)
list.add(i);
// 然后把ans变成数组
int[] ans = new int[list.size()];
int index=0;
for(int i:list){
ans[index++]=i;
}
return ans;
}
}
注意点:使用了ArrayList,不能直接转为int[],只能根据arraylist的size一个个拷贝到int数组里,没有现成的方法函数可以使用。
总结
242很简单。49要用到hashmap,中等难度。438和49差不多。