Valid Anagram

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

For example,
s = "anagram", t = "nagaram", return true.
s = "rat", t = "car", return 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)即交换单词出现顺序的单词。如果对两个单词中出现的字母的频次进行统计。如果所有出现的字母都相同,字母出现的频次也相同,则可以认为是变位词。

以上分析可以看到,hashmap是一个非常好的用来处理这种问题的数据结构。字母第一次出现则将字母作为键放入字典中,值为1,后序出现则增加值。那么对于第二个单词也需要采用同样的做法么?其实不需要,只要逆过来进行处理,如果第二个单词中有字母没有在字典中出现,则肯定不是变位词,返回False,如果出现了,则该键对应的值减1.最后检查是否每个键的键值都是0,当然也可以提前处理,如果某个键的值在减1之前已经变为0,则说明不可能是变位词,提前结束循环。

时间复杂度为O(n),空间复杂度为O(1),小于等于26。

代码如下:

class Solution(object):
    def isAnagram(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        map = {}
        for i in s:
            if i in map:
                map[i] += 1
            else:
                map[i] = 1
        for j in t:
            if j not in map or map[j] == 0:
                return False
            else:
                map[j] -= 1
        return sum(map.values())==0

另外在这里都是小写字母的情况下,则使用一个26位的数组也可以行使hashmap的功能,字母的index为ascii码减去a的ascii码,这样实现免去计算hash key的时间,按道理来说更快一些。时间复杂度为O(n),空间复杂度为O(1),固定26位的一个数组。代码如下:

class Solution(object):
    def isAnagram(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        alphabet = [0]*26
        for i in s:
            alphabet[ord(i) -ord('a')] += 1
        for j in t:
            if alphabet[ord(j) - ord('a')] < 1:
                return False
            else:
                alphabet[ord(j) - ord('a')] -= 1
        
        return sum(alphabet) == 0
        

注意follow up 给出要求说如果字符串包含unicode字符,是否可以处理。显然第一个可以,第二个依靠ascii码的情况不可以。

这题还有第三个思路,但是复杂度较高,就是对两个字符都进行排序,比较排完序后的字符数组是否相同。如果采用普通排序,时间复杂度为O(nlogn)。但是如果采用计数排序(在不包含unicode码的情况下),时间复杂度也是O(n).

posted on 2016-06-27 21:10  Sheryl Wang  阅读(210)  评论(0编辑  收藏  举报

导航