mirror of
https://github.com/halfrost/LeetCode-Go.git
synced 2025-07-12 22:55:19 +08:00
125 lines
2.2 KiB
Go
125 lines
2.2 KiB
Go
package leetcode
|
|
|
|
// 解法一 BFS
|
|
func minMutation(start string, end string, bank []string) int {
|
|
wordMap, que, depth := getWordMap(bank, start), []string{start}, 0
|
|
for len(que) > 0 {
|
|
depth++
|
|
qlen := len(que)
|
|
for i := 0; i < qlen; i++ {
|
|
word := que[0]
|
|
que = que[1:]
|
|
candidates := getCandidates433(word)
|
|
for _, candidate := range candidates {
|
|
if _, ok := wordMap[candidate]; ok {
|
|
if candidate == end {
|
|
return depth
|
|
}
|
|
delete(wordMap, candidate)
|
|
que = append(que, candidate)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
|
|
func getWordMap(wordList []string, beginWord string) map[string]int {
|
|
wordMap := make(map[string]int)
|
|
for i, word := range wordList {
|
|
if _, ok := wordMap[word]; !ok {
|
|
if word != beginWord {
|
|
wordMap[word] = i
|
|
}
|
|
}
|
|
}
|
|
return wordMap
|
|
}
|
|
|
|
func getCandidates433(word string) []string {
|
|
var res []string
|
|
for i := 0; i < 26; i++ {
|
|
for j := 0; j < len(word); j++ {
|
|
if word[j] != byte(int('A')+i) {
|
|
res = append(res, word[:j]+string(rune(int('A')+i))+word[j+1:])
|
|
}
|
|
}
|
|
}
|
|
return res
|
|
}
|
|
|
|
// 解法二 DFS
|
|
func minMutation1(start string, end string, bank []string) int {
|
|
endGene := convert(end)
|
|
startGene := convert(start)
|
|
m := make(map[uint32]struct{})
|
|
for _, gene := range bank {
|
|
m[convert(gene)] = struct{}{}
|
|
}
|
|
if _, ok := m[endGene]; !ok {
|
|
return -1
|
|
}
|
|
if check(startGene ^ endGene) {
|
|
return 1
|
|
}
|
|
delete(m, startGene)
|
|
step := make(map[uint32]int)
|
|
step[endGene] = 0
|
|
return dfsMutation(startGene, m, step)
|
|
}
|
|
|
|
func dfsMutation(start uint32, m map[uint32]struct{}, step map[uint32]int) int {
|
|
if v, ok := step[start]; ok {
|
|
return v
|
|
}
|
|
c := -1
|
|
step[start] = c
|
|
for k := range m {
|
|
if check(k ^ start) {
|
|
next := dfsMutation(k, m, step)
|
|
if next != -1 {
|
|
if c == -1 || c > next {
|
|
c = next + 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
step[start] = c
|
|
return c
|
|
}
|
|
|
|
func check(val uint32) bool {
|
|
if val == 0 {
|
|
return false
|
|
}
|
|
if val&(val-1) == 0 {
|
|
return true
|
|
}
|
|
for val > 0 {
|
|
if val == 3 {
|
|
return true
|
|
}
|
|
if val&3 != 0 {
|
|
return false
|
|
}
|
|
val >>= 2
|
|
}
|
|
return false
|
|
}
|
|
|
|
func convert(gene string) uint32 {
|
|
var v uint32
|
|
for _, c := range gene {
|
|
v <<= 2
|
|
switch c {
|
|
case 'C':
|
|
v |= 1
|
|
case 'G':
|
|
v |= 2
|
|
case 'T':
|
|
v |= 3
|
|
}
|
|
}
|
|
return v
|
|
}
|