力扣哈希表字符串

242. 有效的字母异位词

力扣链接

思路:

利用哈希表,统计两字符串的字符出现次数,最后比较对应字符出现次数是否相等即可。
法一:数组作为哈希表,利用字符对应的ASCII。
法二:直接使用HashMap
法三:快排,异位词其实就是两个相同字符串被打乱字符顺序而产生的。

public boolean isAnagram(String s, String t) {
    //如果仅仅是26字母--可不用HashMap--原始哈希表(数组)
    int ls = s.length();
    if(ls != t.length()) return false;

    int[] num = new int[26];
    for(int i = 0;i < ls; i++) {
    	// 不需要分开统计,直接中和即可。
        num[s.charAt(i)-'a']++;
        num[t.charAt(i)-'a']--;
    }

    for(int n : num){
        if(n != 0) return false;
    }

    return true;
}

输入字符串包含 unicode 字符

public boolean isAnagram(String s, String t) {
    int l = s.length();
    if(l != t.length()) return false;

    HashMap<Character,Integer> map = new HashMap<>();
        
    for(int i =0 ;i < l; i++) {
        //getOrDefault 不存在则置0
        map.put(s.charAt(i),map.getOrDefault(s.charAt(i),0) + 1);
        map.put(t.charAt(i),map.getOrDefault(t.charAt(i),0) - 1);
    }

    for(Integer value : map.values()) {
        if(value != 0) return false;
    }

    return true;
}
//快排
public boolean isAnagram(String s, String t) {
    if(s.length() != t.length()) return false;
    char[] cs = s.toCharArray();
    char[] ct = t.toCharArray();
    Arrays.sort(cs);
    Arrays.sort(ct);
    return Arrays.equals(cs,ct);
}
49. 字母异位词分组

力扣链接

思路:

首先是对异位词的判断(具体见题有效字母异位词),然后需要对异位词进行分组,是异位词的都归为一组。
法一:哈希表判断两字符串是否是异位词,两重for循环进行分组
法二:快排判断异位词+哈希表存放结果
法三:哈希表判断异位词+哈希表存放结果

法一:不推荐,没把哈希表用到极致

    public List<List<String>> groupAnagrams(String[] strs) {
        //其中对于遍历过的无需再次遍历--hash数组的作用
        List<List<String>> res = new ArrayList<>();//结果

        int l = strs.length;
        boolean[] hash = new boolean[l];//记录遍历过的

        for (int i = 0; i < l; i++) {
            if (hash[i] == false) {
                hash[i] = true;
                List<String> tmp = new ArrayList<>();
                tmp.add(strs[i]);

                for (int j = i + 1; j < l; j++) {
                    if (hash[j] == false) {
                        //异位词判断
                        if (hashJudge(strs[i], strs[j])) {
                            hash[j] = true;
                            tmp.add(strs[j]);
                        }
                    }
                }
                res.add(tmp);
            }
        }
        return res;
    }    
    boolean hashJudge(String s1, String s2) {
        int l = s1.length();
        if(l != s2.length()) return false;
        int[] arr = new int[26];
        for(int i =0 ; i < l; i++) {
            arr[s1.charAt(i) - 'a']++; 
            arr[s2.charAt(i) - 'a']--;
        }
        for(int i =0 ; i < 26; i++) {
            if(arr[i] != 0) return false;
        }
        return true;
    }

法二:

    public List<List<String>> groupAnagrams(String[] strs) {        
        int l = strs.length;
        Map<String, List<String>> map = new HashMap<>();

        for(int i = 0; i < l; i++) {
            //快排
            char[] tmp = strs[i].toCharArray();
            Arrays.sort(tmp);
            //排序后的字符串作为key
            String key = new String(tmp);
            //异位词集合作为value
            List<String> list = map.getOrDefault(key, new ArrayList<String>());
            list.add(strs[i]);
            map.put(key,list);
        }
        return new ArrayList<List<String>>(map.values());
    }
    public List<List<String>> groupAnagrams(String[] strs) {        
        int l = strs.length;
        Map<String, List<String>> map = new HashMap<>();

        for(int i = 0; i < l; i++) {
            //快排
            int[] count = new int[26];
            int len = strs[i].length();
            for(int j = 0; j < len; j++) {
                count[strs[i].charAt(j) - 'a']++;
            }
            StringBuilder sb = new StringBuilder();
            //由于遍历从0开始,拼接的串也是有序的,即可作为key
            //拼接时需要拼上次数,代替重复拼接,例如 aaaab  -->  a4b(唯一)
            for(int j = 0; j < 26; j++){                
                if(count[j] != 0) sb.append('a'+ j).append(count[j]);//(char)('a'+ j)转不转都行
            }
            String key = sb.toString();
            //异位词集合作为value
            List<String> list = map.getOrDefault(key, new ArrayList<String>());
            list.add(strs[i]);
            map.put(key,list);
        }
        return new ArrayList<List<String>>(map.values());
    }
409. 最长回文串

力扣链接

思路:

哈希表,统计串中字符的出现次数,其中次数为2的倍数即可加入回文串,这里不是指奇偶数之分,因为5虽然为奇数,但包含4可用,即次数为偶数的话,直接加入回文串,为奇数则减一。最后需要注意一点的,回文串中可以出现有且仅有一个单个字符。所以如果统计过程中出现奇数个数的字符,需要做标记。

  public int longestPalindrome(String s) {
      //哈希数组
      int[] hash= new int[58]; // 'Z' - 'a'
      int l = s.length();
      for(int i = 0; i < l; i++) {
          hash[s.charAt(i)-'A']++;
      }
      int res = 0;
      // 判断是否存在奇数个数的字母--只要存在,最后的长度需加一
      boolean tf = false;
      for(int i = 0; i < 58; i++) {
          if((hash[i] & 1) == 0) {
              //偶数
              res = res + hash[i]; 
          } else {
              //奇数减一
              res = res + hash[i] - 1; 
              tf = true;              
          }            
      }
      return tf == true ? res+1 : res;
    }

除了用标记,也可以用res < l ? res + 1 : res
也就是如果结果等于l,说明不存在奇数个数的字母。全是偶数的,反之亦然。

*205. 同构字符串

力扣链接

思路:

由于题目规定字符顺序不可变,说明串与串之间的字符都是一一对应的,每一个映射关系可以出现多次,但必须相同,例如e->a,后面e->b或者b->a就不行了。
根据映射关系唯一,可通过下标来标识,如果两字符构成的映射关系所对应的下标相同则符合。

    public boolean isIsomorphic(String s, String t) {
        HashMap<Character,Integer> h1 =  new HashMap<>();
        HashMap<Character,Integer> h2 =  new HashMap<>();
        for(int i = 0; i < s.length(); i++) {
            Integer a = h1.get(s.charAt(i));
            Integer b = h2.get(t.charAt(i));
            if(a == null && b == null) { //不存在该映射则添加
                h1.put(s.charAt(i),i);
                h2.put(t.charAt(i),i);
            } else if(a != null && b != null) {// 存在则判断下标是否相同
                if(!a.equals(b)) return false;  
            } else {
                return false;   //仅存在一个也不符合,即相同字符映射到了不同字符上
            }     
        }
        return true;
    }

简化

    public boolean isIsomorphic(String s, String t) {
	    HashMap<Character,Integer> h1 =  new HashMap<>();
	    HashMap<Character,Integer> h2 =  new HashMap<>();
	    for(int i = 0; i < s.length(); i++) {
	        Integer a = h1.get(s.charAt(i));
	        Integer b = h2.get(t.charAt(i));
	        if(a == null && b == null) { //不存在该映射则添加
	            h1.put(s.charAt(i),i);
	            h2.put(t.charAt(i),i);
	        }    
	        if(a != b)  return false;
	    }
	    return true;
    }

如果你是最后一个测试用例没通过,那可能是常量池问题:链接,就是你比较的时候用==或!=,而没用equals,例如129个a的字符串,如果一直put的话,最后一个的value是new Integer(128),也就是对象,而不是常量。你可能会发现上面第二个题解没问题,而链接里的存在问题,这是因为题解添加元素时是有判断的if(a == null && b == null) ,它是只有不存在才添加,也就是对于129个a的字符串,他只会添加第一个。其实该题针对的是可打印的acsii,也就是(32-127),即便不相同的字符也不会出现常量池问题,否则第二个题解同样错。

其它测试用例

"badc"
"baba"
"bbbaaaba"
"aaabbbba"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值