242. 有效的字母异位词

哈希表

  1. class Solution {
  2. public boolean isAnagram(String s, String t) {
  3. Map<Character, Integer> map = new HashMap<>();
  4. for (int i = 0; i < s.length(); ++i){
  5. map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0)+1);
  6. }
  7. for (int i = 0; i < t.length(); ++i){
  8. map.put(t.charAt(i), map.getOrDefault(t.charAt(i), 0)-1);
  9. }
  10. for (Map.Entry<Character, Integer> entry : map.entrySet()){
  11. if (entry.getValue() != 0)
  12. return false;
  13. }
  14. // map也有equals方法
  15. return true;
  16. }
  17. }

排序

  1. class Solution {
  2. public boolean isAnagram(String s, String t) {
  3. if (s.length() != t.length()) {
  4. return false;
  5. }
  6. char[] str1 = s.toCharArray();
  7. char[] str2 = t.toCharArray();
  8. Arrays.sort(str1);
  9. Arrays.sort(str2);
  10. return Arrays.equals(str1, str2);
  11. }
  12. }

49. 字母异位词分组

哈希表+排序

  1. public List<List<String>> groupAnagrams(String[] strs) {
  2. Map<String, List<String>> hm = new HashMap<>();
  3. for (String str : strs){
  4. char[] chars = str.toCharArray();
  5. Arrays.sort(chars);
  6. String newStr = new String(chars);
  7. //说下这里为什么要转成string,因为如果你用char数组,每次new以后地址不同,hash值也不相同
  8. //而string重写了hashcode和euqals方法,只要字符串一致hash的值是一样的
  9. List<String> list = hm.getOrDefault(newStr, new ArrayList<>());
  10. list.add(str);
  11. hm.put(newStr, list);
  12. }
  13. return new ArrayList<>(hm.values());
  14. }

438. 找到字符串中所有字母异位词

我不明白为什么下面这个做法会超时
别人的解释:
image.png
这个说的问题是,下面的滑动窗口里面的,跟我做的没有关系
image.png
image.png
我的做法:感觉这个不叫滑动窗口,时间复杂度好像还是字母异位词 - 图4,如果是排序,是字母异位词 - 图5,得想办法降到字母异位词 - 图6(subString在1.6之前的时间复杂度是O(1),在1.6之后的时间复杂度是O(n))

//原错误解法
class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> ans= new ArrayList<>();
        if (s.length() < p.length()) {
            return ans;
        }
        int left = 0, right = p.length();
        while(right <= s.length()){
            String str = s.substring(left, right); //有人说是这里的问题
            if (isAnagram(str, p)){ //这里也是,都会让时间复杂度变成n方
                ans.add(left);
            }
            left++;
            right++;
        }
        return ans;
    }
    public boolean isAnagram(String s, String t) {
        Map<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < s.length(); ++i){
            map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0)+1);
        }
        for (int i = 0; i < t.length(); ++i){
            map.put(t.charAt(i), map.getOrDefault(t.charAt(i), 0)-1);
            if (map.get(t.charAt(i)) < 0)
                return false;
        }
        return true;
    }
}

//修改解法一:但是使用了hashmap自带的equals方法
class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        int sLen = s.length(), pLen = p.length();

        if (sLen < pLen) {
            return new ArrayList<>();
        }

        List<Integer> ans = new ArrayList<>();
        HashMap<Character, Integer> mapp = new HashMap<>();
        HashMap<Character, Integer> maps = new HashMap<>();
        for (int i = 0; i < pLen; ++i){
            mapp.put(p.charAt(i), mapp.getOrDefault(p.charAt(i), 0)+1);
            maps.put(s.charAt(i), maps.getOrDefault(s.charAt(i), 0)+1);
        }

        if ( mapp.equals(maps) ) //不知道这里的时间复杂度会不会超时
            ans.add(0);

        for (int i = 0; i < sLen - pLen; ++i){
            //maps.put(s.charAt(i), maps.getOrDefault(s.charAt(i), 0)-1);
            maps.put(s.charAt(i), maps.get(s.charAt(i))-1);
            maps.put(s.charAt(i+pLen), maps.getOrDefault(s.charAt(i+pLen), 0)+1);
            if ( mapp.equals(maps) )
                ans.add(i+1);
        }
        return ans;
    }

    public boolean vs(Map<Character,Integer>  map1, Map<Character,Integer>  map2)
    {
        for(Character c:map1.keySet())
            if(!map2.getOrDefault(c, 0).equals(map1.get(c)))
                return false;
        return true;
    }
}

//修改解法二:不使用hashmap自带的equals方法
class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        int sLen = s.length(), pLen = p.length();

        if (sLen < pLen) {
            return new ArrayList<>();
        }

        List<Integer> ans = new ArrayList<>();
        HashMap<Character, Integer> mapp = new HashMap<>();
        HashMap<Character, Integer> maps = new HashMap<>();
        for (int i = 0; i < pLen; ++i){
            mapp.put(p.charAt(i), mapp.getOrDefault(p.charAt(i), 0)+1);
            maps.put(s.charAt(i), maps.getOrDefault(s.charAt(i), 0)+1);
        }

        if ( vs(maps,mapp) ) //不知道这里的时间复杂度会不会超时
            ans.add(0);

        for (int i = 0; i < sLen - pLen; ++i){
            //maps.put(s.charAt(i), maps.getOrDefault(s.charAt(i), 0)-1);
            maps.put(s.charAt(i), maps.get(s.charAt(i))-1);
            maps.put(s.charAt(i+pLen), maps.getOrDefault(s.charAt(i+pLen), 0)+1);
            if ( vs(maps,mapp) )
                ans.add(i+1);
        }
        return ans;
    }

    public boolean vs(Map<Character,Integer>  map1, Map<Character,Integer>  map2)
    {
        for(Character c:map1.keySet())
            if(!map2.getOrDefault(c, 0).equals(map1.get(c)))
                return false;
        return true;
    }
}

使用HashMap的equals方法出错的原因:
因为字符串p的hashmap是不变的,也就是键值对不变,键和值不变;而在窗口移动的过程中,s对应的hashmap是不断变化的,首先就是有的字母对应的值会变为0,这样我们认为他是消失了,但是其键值对仍然存在于hashmap中。他长度都不一样,调用equals方法怎么可能相等呢。

//正确解法
class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        int sLen = s.length(), pLen = p.length();

        if (sLen < pLen) {
            return new ArrayList<Integer>();
        }

        List<Integer> ans = new ArrayList<Integer>();
        int[] sCount = new int[26];
        int[] pCount = new int[26];
        for (int i = 0; i < pLen; ++i) {
            ++sCount[s.charAt(i) - 'a'];
            ++pCount[p.charAt(i) - 'a'];
        }

        if (Arrays.equals(sCount, pCount)) {
            ans.add(0);
        }

        for (int i = 0; i < sLen - pLen; ++i) {
            --sCount[s.charAt(i) - 'a'];
            ++sCount[s.charAt(i + pLen) - 'a'];

            if (Arrays.equals(sCount, pCount)) {
                ans.add(i + 1);
            }
        }

        return ans;
    }
}