题目: 编写一种方法,对字符串数组进行排序,将所有变位词组合在一起。变位词是指字母相同,但排列不同的字符串。
例如:
输入:
第一行:6 //输入的词个数
第二行:["eat", "tea", "tan", "ate", "nat", "bat"]
输入出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
题目评价:
这道题对于会的人来说,比较简单,对于没有做过的人来说,难度较大。我在面试时做过两次,第一次用时27分钟(本人比较菜),第二次10分钟。这道题的两种方法可以用到类似题目的解答上来。
解题思路:
方法一:字母顺序排序
不过变位词的字母顺序如何变化,在对字母进行排序后,都会得到相同顺序的字符。(如abc、bac、cab,在进行排序后都会得到相同的abc)。因此我们可以将排序后的字符串作为哈希表的键值。
package main
import (
"fmt"
"sort"
)
func main() {
strs := make([]string,0)
n := 0
fmt.Scan(&n)
for i:=0 ; i < n ; i++{
var ch string
fmt.Scan(&ch)
strs = append(strs,ch)
}
fmt.Println(getAnagrams(strs))
}
func getAnagrams(strs []string) [][]string {
mp := map[string][]string{}
for _, str := range strs {
s := []byte(str)
sort.Slice(s, func(i, j int) bool { return s[i] < s[j] })
num := string(s)
mp[num] = append(mp[num], str)
}
ans := make([][]string, 0, len(mp))
for _, value := range mp {
ans = append(ans, value)
}
return ans
}
方法二:字母位置计数
和方法一类似,都是运用到互为变位词的两个字符串包含的字母相同,因此两个字符串中的相同字母出现的次数一定时相同的。因此我们可以将每个字母出现的次数用使用哈希来表示(map[字母]次数)。这里存在一个难点:怎么用字母作为键。
package main
import (
"fmt"
)
func main() {
strs := make([]string,0)
n := 0
fmt.Scan(&n)
for i:=0 ; i < n ; i++{
var ch string
fmt.Scan(&ch)
strs = append(strs,ch)
}
fmt.Println(getAnagrams(strs))
}
func getAnagrams(strs []string) [][]string {
mp := map[[26]int][]string{}
for _, str := range strs {
cnt := [26]int{}
for _, b := range str{
cnt[b-'a']++
}
mp[cnt] = append(mp[cnt],str)
}
ans := make([][]string,0,len(mp))
for _, v := range mp {
ans = append(ans,v)
}
return ans
}