目录
思路
构建一个映射表,记录ring中每个下标向前向后到达每个字母的距离。然后BFS枚举,只枚举当前位置向前向后的到达目标字符,并记录。
枚举的时候采用了一些小优化,map的重复使用,以及只记录需要遍历的pos等等。
代码
func findRotateSteps(ring string, key string) int {
dist := make([][][]int, len(ring))
nRing := len(ring)
nKey := len(key)
for i := 0; i < nRing; i++ {
dist[i] = make([][]int, 2)
dist[i][0] = make([]int, 26)
dist[i][1] = make([]int, 26)
for k := 0; k < 26; k++ {
dist[i][0][k] = -1
dist[i][1][k] = -1
}
dist[i][0][int(ring[i]-'a')] = 0
dist[i][1][int(ring[i]-'a')] = 0
for j := i + 1; j < nRing; j++ {
if dist[i][0][int(ring[j]-'a')] == -1 || dist[i][0][int(ring[j]-'a')] > j-i {
dist[i][0][int(ring[j]-'a')] = j - i
}
if dist[i][1][int(ring[j]-'a')] == -1 || dist[i][1][int(ring[j]-'a')] > i+nRing-j {
dist[i][1][int(ring[j]-'a')] = i + nRing - j
}
}
for j := 0; j < i; j++ {
if dist[i][0][int(ring[j]-'a')] == -1 || dist[i][0][int(ring[j]-'a')] > nRing+j-i {
dist[i][0][int(ring[j]-'a')] = nRing + j - i
}
if dist[i][1][int(ring[j]-'a')] == -1 || dist[i][1][int(ring[j]-'a')] > i-j {
dist[i][1][int(ring[j]-'a')] = i - j
}
}
}
cnt := 0
hasM := make([]int, nRing)
stepM := make([]int, nRing)
posArr := make([]int, 0, nRing)
next := func(curPos, curStep, next int) {
beforStep := curStep + dist[curPos][1][next] + 1
beforPos := (curPos - dist[curPos][1][next] + nRing) % nRing
afterStep := curStep + dist[curPos][0][next] + 1
afterPos := (curPos + dist[curPos][0][next]) % nRing
if hasM[beforPos] != cnt {
stepM[beforPos] = beforStep
posArr = append(posArr, beforPos)
hasM[beforPos] = cnt
} else {
if stepM[beforPos] > beforStep {
stepM[beforPos] = beforStep
}
}
if hasM[afterPos] != cnt {
stepM[afterPos] = afterStep
posArr = append(posArr, afterPos)
hasM[afterPos] = cnt
} else {
if stepM[afterPos] > afterStep {
stepM[afterPos] = afterStep
}
}
}
curPosArr := make([]int, 1, nRing)
for i := 0; i < nKey; i++ {
cnt++
for _, curPos := range curPosArr {
next(curPos, stepM[curPos], int(key[i]-'a'))
}
curPosArr, posArr = posArr, curPosArr[:0]
}
min := int(0x7fffffff)
for _, curPos := range curPosArr {
if stepM[curPos] < min {
min = stepM[curPos]
}
}
return min
}
复杂度分析
构建距离表,O(len(ring)*len(ring))
BFS到达终点,O(len(key)*len(ring)), posArr 中的点最多也就len(ring)个,实际情况可能比最差的情况好得多,因为我们每次只搜索了向前和向后最近到达目标字符的点