给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/
思路是构建一棵树或者DFS。
我假想了树的形式,预先申请了叶子节点数量的字符串数组,然后构建下标表达式,将结果放到相应的位置。
可惜做题的时候跳了好多个坑,干的活又累又久:
- range遍历方法返回的第二个值,就仅仅是值而已,对它直接修改不会对字符串有任何改变。
- append第一个操作数是切片,不能对字符串直接操作(正确做法应该是对[]byte操作),不像c++里的push_back。
- 使用函数修改字符串,当然得传地址进函数。
- ReplaceAll(字符串的大多数操作)有返回值,干调用没有结果,需要赋值行为改变值。
- golang字符串拼接会产生很多个子串拷贝,对内存而言这样的代码不太健康,不知道有什么更好的方法
import "strings"
func appendStr(str *[]string, numstr string, plen int) int {
var left, right, cnt int
for j := 1; j <= plen; j++ {
left = (j - 1) * len(*str) / plen
right = j * len(*str) / plen
for i := 0; i < right-left; i++ {
cnt = (right - left) / len(numstr)
(*str)[left+i] = strings.ReplaceAll((*str)[left+i], (*str)[left+i], (*str)[left+i]+numstr[i/cnt:i/cnt+1])
}
}
return plen * len(numstr)
}
func letterCombinations(digits string) []string {
vlen := 1
for _, v := range digits {
if v == '7' || v == '9' {
vlen *= 4
} else if v != '*' && v!= '#' && v!='1' {
vlen *= 3
}
}
if vlen == 1{
vlen = 0
}
restr := make([]string, vlen)
vlen = 1
for _, v := range digits {
switch v {
case '2': vlen = appendStr(&restr, "abc", vlen)
case '3': vlen = appendStr(&restr, "def", vlen)
case '4': vlen = appendStr(&restr, "ghi", vlen)
case '5': vlen = appendStr(&restr, "jkl", vlen)
case '6': vlen = appendStr(&restr, "mno", vlen)
case '7': vlen = appendStr(&restr, "pqrs", vlen)
case '8': vlen = appendStr(&restr, "tuv", vlen)
case '9': vlen = appendStr(&restr, "wxyz", vlen)
}
}
return restr
}