我尝试用BFS解决this问题,但是对于输入" 99 100"我的程序使用超过260 Mb并且在线判断系统抛出MEMORY_LIMIT_EXCEEDED。我想问题是我使用QUEUE的方式。那么您认为这是什么问题?我该如何解决呢?
这是我的代码。并提前感谢!:
package main
import (
"fmt"
)
type pair struct {
nn int
dd int
}
func main() {
var n, m int
fmt.Scanf("%d%d", &n, &m)
if n >= m {
fmt.Println(n - m)
} else {
device := make([]pair, 1)
device[0] = pair{n, 0}
ans := 0
for {
// pop front element
tmp := device[0]
device = device[1:]
if tmp.nn == m { // reached destination
ans = tmp.dd
break
}
// add neighbors to the queue
device = append(device, pair{tmp.nn - 1, tmp.dd + 1})
device = append(device, pair{tmp.nn * 2, tmp.dd + 1})
}
fmt.Println(ans)
}
}
编辑:更具可读性和工作性(已接受)代码:
package main
import (
"fmt"
)
type pair struct {
location int
dist int
}
func main() {
var n, m int
fmt.Scanf("%d%d", &n, &m)
if n >= m {
fmt.Println(n - m)
} else {
visited := make([]bool, m+2)
queue := make([]pair, 1)
queue[0] = pair{n, 0}
ans := 0
visited[n] = true
for {
// pop front element
tmp := queue[0]
queue = queue[1:]
// reached destination
if tmp.location == m {
ans = tmp.dist
break
}
// add neighbors to the queue
if tmp.location*2 <= m+1 && visited[tmp.location*2] == false {
queue = append(queue, pair{tmp.location * 2, tmp.dist + 1})
visited[tmp.location*2] = true
}
if tmp.location-1 >= 0 && visited[tmp.location-1] == false {
queue = append(queue, pair{tmp.location - 1, tmp.dist + 1})
visited[tmp.location-1] = true
}
}
fmt.Println(ans)
}
}
答案 0 :(得分:1)
您的算法不是BFS,因为您可以访问多个相同的状态。
例如,4 - &gt; 3 - &gt; 6和4 - &gt; 8 - &gt; 7 - &gt; 6,其中6将最终被处理两次。
其次,对于大于x
的数字target
,最小步数始终为
x - target + step to reach x
所以你不应该把它添加到队列中。
通过进行这两项修改,空间复杂度将限制为O(m),这可以帮助您解决问题。
示例代码
ans := -1
dist := make([]int, m + 1)
q := make([]int,1)
q[0] = n
for i := 0; i < len(q); i++ {
node := q[i]
if node == m {
if ans == -1 || ans > dist[m]{
ans = dist[m]
}
break;
}
a := node*2
b := node - 1
if a >= m {
if ans == -1 || ans > (1 + dist[node] + a - m) {
ans = 1 + dist[node] + a - m
}
}else if dist[a] == 0 && a != n {
q = append(q, a)
dist[a] = 1 + dist[node]
}
if dist[b] == 0 && b != n {
q = append(q, b)
dist[b] = 1 + dist[node]
}
}
return ans
答案 1 :(得分:0)
乍一看告诉我,对于你拥有的每个dd
,队列中将有2^dd
个元素。并且答案预计会大于50,这是一个保证的内存限制超过。
一个非常简单和常见的优化是跟踪被访问的节点(在您的情况下为nn
)。创建map[int]bool
(因为dd
只是增加,因此没有理由记录上次访问的值)并且不会添加到队列中。
评论中提到的另一个优化是,不要将nn
大于targets
添加到队列中。这有点复杂,因为您需要记录值res = min(res, dd+nn-target)
,其中nn
是大于目标的值,dd
是获取值的步骤。如果当前dd大于res,你也想要中断。
接受答案的代码有错误。它从不试图确定b
是否小于零。考虑到设计的测试用例,可能会发生范围索引的运行时恐慌。