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?
Solution:
這題看上去和 383. Ransom Note 差不多,都是求后者是不是可以由前者所含有的字符置換順序所得。但不同之處在于 Ransom Note 不需要用完前者所有的字符,而這里需要用完前者所有的字符。
順著這個思路,在 Ransom Note的基礎上最后用iterator在values的Collection中遍歷一遍看是否都為0了,如果有大于0的說明該字符沒有被后者用完,也就不是Anagram了。
注意1:迭代器Iterator<T> 有個重要的性質(zhì)是當?shù)谝淮螆?zhí)行next()方法后,指向首個元素,而不是第二個元素。
注意2: 迭代器是一個泛型,類型T為定義它時需要它指向的元素的類型。
注意3:當需要返回HashMap上的迭代器時,注意是hashMap.keySet().iterator() 還是 hashMap.values().iterator()。前者返回一個包含所有key值的Set上的迭代器,后者返回一個包含所有value值的Collection上的迭代器。(Set上不允許重復,Collection上可以有重復元素)
注意4:還可以通過 EntrySet().iterator() 上的迭代器來遍歷
Code:
public class Solution
{
public boolean isAnagram(String s, String t)
{
HashMap<Character, Integer> hm = new HashMap<>();
for(int i = 0; i < s.length(); i++)
{
int newCount = hm.getOrDefault(s.charAt(i), 0) + 1;
hm.put(s.charAt(i), newCount);
}
for(int j = 0; j < t.length(); j++)
{
int newCount = hm.getOrDefault(t.charAt(j), 0) - 1;
if(newCount < 0)
return false;
else
hm.put(t.charAt(j), newCount);
}
Iterator<Integer> itr = hm.values().iterator();
while(itr.hasNext())
{
if(itr.next() > 0)
return false;
}
return true;
}
}
然而參考Discussion后發(fā)現(xiàn)自己思維慣性了。后者是否是由前者所有的字符組合而來的一個必要條件就是兩者的長度首先要相等。在長度相等的情況下,就可以直接使用Ransom Note的思路(因為等長的情況下不會出現(xiàn)沒有用盡前者中的字符就已經(jīng)組合齊全了)
public boolean isAnagram(String s, String t)
{
if(s.length() != t.length())
return false;
HashMap<Character,Integer> map = new HashMap<>();
for(Character c : s.toCharArray())
{
int count = map.getOrDefault(c,0)+1;
map.put(c,count);
}
for(Character c : t.toCharArray())
{
int count = map.getOrDefault(c,0)-1;
if(count < 0) return false;
map.put(c,count);
}
return true;
}