LeetCode 242. Valid Anagram

题目

Given two strings s and , write a function to determine if t is an anagram of s.

Example 1:

Input: s = "anagram", t = "nagaram"
Output: true

Example 2:

Input: s = "rat", t = "car"
Output: false

Note:
You may assume the string contains only lowercase alphabets.

Follow up:
What if the inputs contain unicode characters? How would you adapt your solution to such case?


这道题是求两个给定的字符串是不是anagram,anagram的定义就是两个字符串由完全相同的字母和个数组成。

看到这道题第一个想到的办法就是分别对s和t计算每个字母出现了多少次,可以采用unordered_map存储,然后比较两个unordered_map是否相同。这种写法的时间复杂度是O(n),空间复杂度也是O(n),但是存储了两个unordered_map。运行时间16ms,55.27%,空间9.4M,88.06%:

class Solution {
public:
    bool isAnagram(string s, string t) {
        unordered_map<char, int> chars_s;
        for (int i = 0; i < s.size(); i++) {
            if (chars_s.count(s[i]) == 0) {
                chars_s[s[i]] = 1;
            }
            else {
                chars_s[s[i]]++;
            }
        }
        unordered_map<char, int> chars_t;
        for (int i = 0; i < t.size(); i++) {
            if (chars_t.count(t[i]) == 0) {
                chars_t[t[i]] = 1;
            }
            else {
                chars_t[t[i]]++;
            }
        }
        return chars_s == chars_t;
    }
};

2022.11.9 果然还是先想到了这个最简单粗暴的方法

class Solution {
    public boolean isAnagram(String s, String t) {
        return countChar(s).equals(countChar(t));
    }
    private Map<Character, Integer> countChar(String s) {
        Map<Character, Integer> map = new HashMap<>();
        for (char c : s.toCharArray()) {
            map.put(c, map.getOrDefault(c, 0) + 1);
        }
        return map;
    }
}

 后来看了discussion才意识到还可以直接使用一个unordered_map解决。自己想到的办法是,先对s进行一次遍历存入unordered_map,然后在遍历t的时候,在对应的key-value pair里面把value--。刚开始写的时候没有考虑到两个字符串长度不同,可能会出现t中的value都减完了但是s中还有多的(比如"ab", "a"的情况,多了个b),所以需要在前面提前判断字符串的长度,如果不同的话直接返回0。这种方法其实不是个好方法,运行时间28ms,21.81%,空间9.4M,88.06%:

class Solution {
public:
    bool isAnagram(string s, string t) {
        if (s.size() != t.size()) {
            return false;
        }
        unordered_map<char, int> chars_s;
        for (int i = 0; i < s.size(); i++) {
            if (chars_s.count(s[i]) == 0) {
                chars_s[s[i]] = 1;
            }
            else {
                chars_s[s[i]]++;
            }
        }
        for (int i = 0; i < t.size(); i++) {
            if (chars_s[t[i]] != 0) {
                chars_s[t[i]]--;
            }
            else {
                return false;
            }
        }
        return true;
    }
};

2022.11.9 这个方法我现在不知道意义何在,直接拿数组不香么。


还有一种做法只需要进行一次遍历,就是在每次遍历的过程中,对s中出现的字符的个数++,对t中出现的字符的个数--。刚开始觉得要先初始化为0好像很麻烦,但发现其实可以不用初始化,猜测原因是unordered_map<char, int>在初始化一个char对应的value时自动填0,于是就能直接++和--,非常方便。这种情况下时间复杂度也要小一倍。时间12ms,81.09%,空间9.4M,86.57%:

class Solution {
public:
    bool isAnagram(string s, string t) {
        if (s.size() != t.size()) {
            return false;
        }
        unordered_map<char, int> chars;
        for (int i = 0; i < s.size(); i++) {
            chars[s[i]]++;
            chars[t[i]]--;
        }
        for (unordered_map<char, int>::iterator it = chars.begin(); it != chars.end(); it++) {
            if (it->second != 0) {
                return false;
            }
        }
        return true;
    }
};

2022.11.9 同理,这个方法我现在不知道意义何在,直接拿数组不香么。


上面这种做法还可以简化为直接用数组,相当于把hash_map的key当作数组的下标,顺序地将0-25赋给a-z,听说可以加快运行速度。12ms,81.09%,9.6M,55.22%:

class Solution {
public:
    bool isAnagram(string s, string t) {
        if (s.size() != t.size()) {
            return false;
        }
        char chars[26] = {0};
        for (int i = 0; i < s.size(); i++) {
            chars[s[i] - 'a']++;
            chars[t[i] - 'a']--;
        }
        for (int i = 0; i < 26; i++) {
            if (chars[i] != 0) {
                return false;
            }
        }
        return true;
    }
};

2022.11.9

了解思路以后秒写出来了。

class Solution {
    public boolean isAnagram(String s, String t) {
        if (s.length() != t.length()) {
            return false;
        }
        int[] array = new int[26];
        for (int i = 0; i < s.length(); i++) {
            char sc = s.charAt(i);
            char tc = t.charAt(i);
            array[sc - 'a']++;
            array[tc - 'a']--;
        }

        for (int i : array) {
            if (i != 0) {
                return false;
            }
        }
        return true;
    }
}

最后还有一种做法就是万能的sort,因为anagram所有包含的字母个数都一样,所以sort完的字符串一定是一样的。时间复杂度为sort的O(nlogn),空间复杂度也根据sort算法来看。运行时间36ms,6.94%(不忍直视),空间0.5M,79.1%:

class Solution {
public:
    bool isAnagram(string s, string t) {
        sort(s.begin(), s.end());
        sort(t.begin(), t.end());
        
        return s == t;
    }
};

2022.11.9

代码也很简单,得先toCharArray以后再Arrays.sort(),然后Arrays.equals()

class Solution {
    public boolean isAnagram(String s, String t) {
        char[] sChar = s.toCharArray();
        char[] tChar = t.toCharArray();
        Arrays.sort(sChar);
        Arrays.sort(tChar);
        return Arrays.equals(sChar, tChar);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值