同母一异序词:两个字符串由相同字符组成,字符顺序可以不一致。
242. Valid Anagram
Given two strings s and t , 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.
判断两个字符串是否为同母异序词
解法一,将两个字符串字符排序,比较排序后的字符串是否相等。
public boolean isAnagram(String s, String t) {
char[] sa = s.toCharArray();
Arrays.sort(sa);
char[] ta = t.toCharArray();
Arrays.sort(ta);
return String.valueOf(sa).equals(String.valueOf(ta));
}
Complexity analysis
-
Time complexity : O(n \log n)O(nlogn). Assume that nn is the length of ss, sorting costs O(n \log n)O(nlogn) and comparing two strings costs O(n)O(n). Sorting time dominates and the overall time complexity is O(n \log n)O(nlogn).
-
Space complexity : O(1)O(1). Space depends on the sorting implementation which, usually, costs O(1)O(1) auxiliary space if
heapsort
is used. Note that in Java,toCharArray()
makes a copy of the string so it costs O(n)O(n) extra space, but we ignore this for complexity analysis because:- It is a language dependent detail.
- It depends on how the function is designed. For example, the function parameter types can be changed to
char[]
.
解法二,如果全部为小写字母,则可以使用哈希表来比较两个字符串
声明int[26]数组,利用字符串中字符相对于字符‘a’的顺序来作为字符表示在数组中的索引,利用数组中值为该字符出现的次数。
//如果全为小写字母,则可以使用hash table来实现
public boolean isAnagram2(String s, String t) {
int[] table = new int[26];
for(char c : s.toCharArray()){
table[c-'a']++;
}
for(char c : t.toCharArray()){
table[c-'a']--;
}
//如果此时table全部为零,说明两个字符串由相同字符组成,为同母异序词
for(int i : table){
if(i != 0)
return false;
}
return true;
}
Complexity analysis
-
Time complexity : O(n)O(n). Time complexity is O(n)O(n) because accessing the counter table is a constant time operation.
-
Space complexity : O(1)O(1). Although we do use extra space, the space complexity is O(1)O(1) because the table's size stays constant no matter how large nn is.
Follow up:
What if the inputs contain unicode characters? How would you adapt your solution to such case?
如果字符集很大,则如果分配一个大型数组,则非常浪费空间,此时可以使用hashtable来进行映射,仅仅记录出现的字符以及出现的次数。
49. Group Anagrams
Given an array of strings, group anagrams together.
Example:Input: ["eat", "tea", "tan", "ate", "nat", "bat"]
, Output: [ ["ate","eat","tea"], ["nat","tan"], ["bat"] ]
Note:
- All inputs will be in lowercase.
- The order of your output does not matter.
将同母异序词进行分组输出
解法一,利用Map<String,List>其中String key为字符串排序后的字符串,如果排序后相等,则说明为同母异序词。
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for(String str : strs){
char[] ca = str.toCharArray();
Arrays.sort(ca);
String s = String.valueOf(ca);
if(map.get(s) == null){
List<String> l = new ArrayList<>();
l.add(str);
map.put(s, l);
}else{
map.get(s).add(str);
}
}
return new ArrayList<>(map.values());
}
解法二,利用某种规则来标识同母异序词,利用数组索引以及数组值,数组索引标识某个字符a-z,数组值表示字符出现次数,将数组索引转换为特定规则的字符串,26个#,每个#后面的数字表示字符出现的此时,例如
public List<List<String>> groupAnagrams2(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
int[] count = new int[26];
for(String str : strs){
Arrays.fill(count, 0);
char[] ca = str.toCharArray();
for(char c : ca){
count[c-'a']++;
}
StringBuilder sb = new StringBuilder();
for(int i : count){
sb.append("#");
sb.append(i);
}
String s = sb.toString();
if(map.get(s) == null)
map.put(s, new ArrayList<>());
map.get(s).add(str);
}
return new ArrayList<>(map.values());
}