今天我们主要刷的是哈希表相关的题目
041 、有效的字母异位词
题目描述
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
思路1
我一开始用的哈希表来做,思路是用map记录s中所有的字符及其个数,遍历t字符串,在map中给每个遍历到的字符减一,如果某个字符减为0就remove。如果遍历到的字符不在map中,说明某个字符在两个字符串中的个数是不一样的,return false,最后遍历完成,如果map中还有元素,说明不同,如果没有,说明二者是异位词
class Solution {
public boolean isAnagram(String s, String t) {
Map<Character,Integer> mps = new HashMap<>();
int lens=s.length();
int lent=t.length();
for(int i=0;i<lens;i++){
mps.put(s.charAt(i),mps.getOrDefault(s.charAt(i),0)+1);
}
for(int i=0;i<lent;i++){
if(mps.get(t.charAt(i))!=null){
mps.put(t.charAt(i),mps.get(t.charAt(i))-1);
if(mps.get(t.charAt(i))==0)mps.remove(t.charAt(i));
}else return false;
}
if(mps.isEmpty())return true;
else return false;
}
}
思路2
后来看题解发现还有一种更简洁的思路,就将字符串的字符排序,如果是异位词,排序后肯定是相同的字符串
class Solution {
public boolean isAnagram(String s, String t) {
char[] sc = s.toCharArray();
Arrays.sort(sc);
char[] tc = t.toCharArray();
Arrays.sort(tc);
if(Arrays.equals(sc,tc))return true;
else return false;
}
}
042 、赌金信
题目描述
给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
如果可以,返回 true ;否则返回 false 。
magazine 中的每个字符只能在 ransomNote 中使用一次。
思路
这个题就更适合用哈希表来做了,我们可以和刚才相同的思路
我一开始用的哈希表来做,思路是用map记录s中所有的字符及其个数,遍历t字符串,在map中给每个遍历到的字符减一,如果某个字符减为0就remove。如果遍历到的字符不在map中,说明某个字符在两个字符串中的个数是不一样的,return false,最后遍历完成,如果map中还有元素,说明不同,如果没有,说明二者是异位词
不一样的地方是,最后的map可以不是空的
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
Map<Character,Integer> mps = new HashMap<>();
int lens=magazine.length();
int lent=ransomNote.length();
for(int i=0;i<lens;i++){
mps.put(magazine.charAt(i),mps.getOrDefault(magazine.charAt(i),0)+1);
}
for(int i=0;i<lent;i++){
if(mps.get(ransomNote.charAt(i))!=null){
mps.put(ransomNote.charAt(i),mps.get(ransomNote.charAt(i))-1);
if(mps.get(ransomNote.charAt(i))==0)mps.remove(ransomNote.charAt(i));
}else return false;
}
return true;
}
}
043 、字母异位词分组
题目描述
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
示例 1:
输入: strs = [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
输出: [[“bat”],[“nat”,“tan”],[“ate”,“eat”,“tea”]]
思路
这个题我一开始也是用哈希表来做的,不过时间复杂度太高了,没办法ac。看了题解后使用排序+哈希表,还是很巧妙的。
以字符串排序后的string作为key,以所有排序后为string的字符串的list作为value
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String,List<String>> map=new HashMap<>();
for(String s:strs){
char[] c=s.toCharArray();
Arrays.sort(c);
String temp=new String(c);
List list=map.getOrDefault(temp,new ArrayList<String>());
list.add(s);
map.put(temp,list);
}
List<List<String>> ans=new ArrayList<List<String>>(map.values());
return ans;
}
}
044 、找到字符串中所有字母异位词
题目描述
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
思路
我一开始使用哈希表来做的,这样的复杂度是O(m*n),会超时间
for(int i=0;i<lens-lenp+1;i++){
if(isAnagram( s.substring(i,i+lenp),p)){
ans.add(i);
}
}
看完答案后发现要用滑动窗口来做,这么明显的滑动窗口我竟然没看出来真是罪过啊
class Solution {
int[] pcnt=new int[26];
int[] cnt=new int[26];
public boolean check(){
for(int i=0;i<26;i++){
if(cnt[i]!=pcnt[i])return false;
}
return true;
}
public List<Integer> findAnagrams(String s, String p) {
for(int i=0;i<p.length();i++)pcnt[p.charAt(i)-'a']++;
List<Integer> ans=new ArrayList<Integer>();
int lens=s.length();
int lenp=p.length();
int l=0,r=0;
for(r=0;r<lens;r++){
cnt[s.charAt(r)-'a']++;
while(r-l+1==lenp){
if(check())ans.add(l);
cnt[s.charAt(l++)-'a']--;
}
}
return ans;
}}
结语
最近刚开始用java刷算法题,好不习惯啊,好多操作细节需要重新学习,哎