[哈希表 排序] 242. 有效的字母异位词(排序法、哈希表法 → 空间优化)

[哈希表 排序] 242. 有效的字母异位词(排序法、哈希表法 → 空间优化)

242. 有效的字母异位词

题目链接:https://leetcode-cn.com/problems/valid-anagram/

解题思路类似:剑指offer面试题50


分类:

  • 排序(将字符串转成字符数组,Arrays.sort对字符数组排序)
  • 哈希表(key = 字符,value = 出现次数、空间优化:用固定大小的数组代替哈希表)

在这里插入图片描述

思路1:排序

将字符串转换成字符数组,然后调用Arrays.sort能够对每个字符按ASCII大小做升序排列;

排序后的两个字符数组一一比较每一位字符,如果出现同一下标的字符不相同,则返回false;如果两个字符数组完全相同,返回true。

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

        char[] sch = s.toCharArray();
        char[] tch = t.toCharArray();
        Arrays.sort(sch);
        Arrays.sort(tch);
        for(int i = 0; i < sch.length; i++){
            if(sch[i] != tch[i]) return false;
        }
        return true;
    }
}
  • 时间复杂度:排序要用O(NlogN),检验需要O(N),所以整体为O(NlogN)
  • 空间复杂度:字符串转字符数组需要开辟O(2N)的空间。

思路2:使用map

map存放第一个字符串的所有字符和对应的出现次数;

再遍历第二个字符串,每遇到map中存在的字符则value-1,若map中不存在该字符,直接return false;

遍历结束后,若map全部value=0,return true;否则return false;

//思路2(兼容进阶提到的情况)
class Solution {
    public boolean isAnagram(String s, String t) {
        if(s.length() != t.length()) return false;

        Map<Character, Integer> map = new HashMap<>();
        for(int i = 0; i < s.length(); i++){
            int svalue = map.getOrDefault(s.charAt(i), 0);
            map.put(s.charAt(i), svalue + 1);
            int tvalue = map.getOrDefault(t.charAt(i), 0);
            map.put(t.charAt(i), tvalue - 1);
        }
        //遍历map中所有value,如果存在一个value!=0,返回false;所有value都为0,才返回true
        for(Integer value : map.values()){
            if(value != 0) return false;
        }
        return true;
    }
}
  • 时间复杂度:O(N),遍历两次字符串+枚举map所有键值对
  • 空间复杂度:O(N).

空间优化:因为可能出现的字符范围是已知的26个小写字母,所以可以开辟一个大小为26的数组count来记录字符的出现次数。空间复杂度可以优化为O(1)

时间优化:一次遍历完全可以同时处理两个字符串,如果是s上的字符,count数组对应位置+1,如果是t上的字符,count数组对应位置-1.时间优化为:遍历一次字符串+遍历一次count数组

//思路2优化代码
class Solution {
    public boolean isAnagram(String s, String t) {
        if(s.length() != t.length()) return false;

        //创建固定大小的数组存放每个字符出现的次数
        int[] count = new int[26];

        //遍历第一个字符数组,统计每个字符的出现次数
        for(int i = 0; i < s.length(); i++){
            count[ s.charAt(i) - 'a']++;
            count[ t.charAt(i) - 'a']--;
        }
        //最后再遍历一次count数组,如果全为0说明两字符串是字母异位词
        for(int i : count){
            if(i != 0)
                return false;
        }
        return true;
    }
}

进阶:unicode字符是使用两个字节来存放各种字符,能够表示的字符为2^16个,可以用来表示汉字等多种语言。

带来的影响:不能再像思路1的改进措施那样开辟一个固定大小的数组来保存对应字符的出现次数,但使用map可以兼容unicode字符。(思路2使用map的代码仍然适用)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值