2021-02-18:給定一個字符串str,給定一個字符串類型的數組arr,出現的字符都是小寫英文。arr每個字符串,表明一張貼紙,你能夠把單個字符剪開使用,目的是拼出str來。返回須要至少多少張貼紙能夠完成這個任務。例子:str= "babac",arr = {"ba","c","abcd"}。a + ba + c 3 abcd + abcd 2 abcd+ba 2。因此返回2。java
福哥答案2021-02-18:
天然智慧便可。
帶記憶的遞歸。對「babac」排序,變成「aabbc」,而後根據數組,依次消掉a,而後b,最後c,這是一個優化點。有代碼。
代碼用golang編寫,代碼以下:git
package main import ( "fmt" "strings" ) const MAX = int(^uint(0) >> 1) //構造0111111111.... 9223372036854775807 const MIN = int(^MAX) //構造10000000... -9223372036854775808 func main() { ret := minStickers([]string{"ba", "c", "abcd"}, "babac") fmt.Println(ret) } func minStickers(stickers []string, target string) int { N := len(stickers) counts := make([][]int, N) for i := 0; i < N; i++ { counts[i] = make([]int, 26) } for i := 0; i < N; i++ { str := stickers[i] for _, cha := range str { counts[i][cha-'a']++ } } dp := make(map[string]int) dp[""] = 0 ans := process(counts, target, dp) if ans == MAX { return -1 } else { return ans } } func process(stickers [][]int, t string, dp map[string]int) int { if _, ok := dp[t]; ok { return dp[t] } tcounts := make([]int, 26) for _, cha := range t { tcounts[cha-'a']++ } N := len(stickers) min := MAX for i := 0; i < N; i++ { sticker := stickers[i] if sticker[t[0]-'a'] > 0 { builder := strings.Builder{} for j := 0; j < 26; j++ { if tcounts[j] > 0 { nums := tcounts[j] - sticker[j] for k := 0; k < nums; k++ { builder.WriteByte('a' + byte(j)) } } } rest := builder.String() min = getMin(min, process(stickers, rest, dp)) } } ans := min if min != MAX { ans++ } dp[t] = ans return ans } func getMin(a int, b int) int { if a < b { return a } else { return b } }
執行結果以下:github