/*
暴力递归
暴力递归的过程就是尝试
1.把问题转化为规模缩小了的同类问题的子问题
2.有明确的不需要继续进行递归的条件(base case)
3.有当得到了子问题的结果之后的决策过程
4.不记录每一个子问题的解 记录则为动态规划
*/
/*
熟悉什么叫尝试
。打印n层汉诺塔从最左边移动到最右边的全部过程
。打印一个字符串的全部子序列
。打印一个字符串的全部子序列,要求不要出现重复字面值的子序列
。打印一个字符串的全部排列
。打印一个字符串的全部排列,要求不要出现重复排列
*/
/*
| | |
--- | |
----- | |
------- | |
左 中 右
主视图
小压大的次序将左侧柱子上的盘子移动的右侧的柱子上去,可以借助中间的柱子
O O
O
俯视图
1. 1 ~ N-1 左 --> 中
2. N 左 --> 右
3. 1 ~ N-1 中 --> 右
*/
func hanoi1(n int) {
leftToRight(n)
}
// 把1~N层圆盘,从左 -> 右
func leftToRight(n int) { //1-n层全部圆盘
if n == 1 { //base case 只剩一个
fmt.Println("Move 1 from left to right")
return
}
leftToMid(n - 1)
fmt.Println("Move", n , "from left to right")
midToRight(n - 1)
}
// 把1~N层圆盘,从左 -> 中
func leftToMid( n int) {
if n == 1 {
fmt.Println("Move 1 from left to mid")
return
}
leftToRight(n - 1)
fmt.Println("Move",n,"from left to mid")
rightToMid(n - 1 )
}
// 把1~N层圆盘,从 右 -> 中
func rightToMid(n int){
if n == 1 {
fmt.Println("Move 1 from right to mid")
return
}
rightToLeft(n - 1)
fmt.Println("Move",n,"from right to mid")
leftToMid(n - 1)
}
func midToRight(n int) {
if n == 1 {
fmt.Println("Move 1 fromo mid to right")
return
}
midToLeft(n - 1)
fmt.Println("Move",n,"from mid to right")
leftToRight(n - 1)
}
func rightToLeft(n int) {
if n == 1 {
fmt.Println("Move 1 from right to left")
return
}
rightToMid(n - 1)
fmt.Println("Move",n,"from right to left")
midToLeft(n - 1)
}
func midToLeft(n int) {
if n == 1 {
fmt.Println("Move 1 from mid to left")
return
}
midToRight(n - 1)
fmt.Println("Move",n,"from mid to left")
rightToLeft(n - 1)
}
func TestHanoi1(t *testing.T) {
hanoi1(3)
}
/*
1. 1~N-1 from -> other
2. N from -> to
3. 1~N-1 other -> to
*/
func hanoi2(n int) {
if n > 0 {
hanoi(n,"left","right","mid")
}
}
func hanoi(N int, from, to, other string) {
if N == 1 {
fmt.Println("Move 1 from",from,"to",to)
return
}else {
hanoi(N - 1,from , other,to)
fmt.Println("Move",N,"from",from,"to",to)
hanoi(N-1,other,to,from)
}
}
func TestHanoi2(t *testing.T) {
hanoi2(10)
}
/*
3层为例
1. 1,2 左 --> 中 | 1 左 --> 右
| 2 左 --> 中
| 1 右 --> 中
2. 3 左 --> 右
3. 1,2 中 --> 右 | 1 中 --> 左
| 2 中 --> 右
| 1 左 --> 右
N层汉诺塔最优解复杂度O(2^N-1)
*/
type Record struct {
finish bool
base int
from string
to string
other string
}
type RecordStack struct {
Elem []Record
}
func NewRecordStack() *RecordStack {
return &RecordStack{Elem: make([]Record,0)}
}
func (s *RecordStack)Push(val Record) {
s.Elem = append(s.Elem, val)
}
func (s *RecordStack)Pop() Record {
res := s.Elem[len(s.Elem)-1]
s.Elem = s.Elem[:len(s.Elem)-1]
return res
}
func (s *RecordStack)Peek() *Record {
return &s.Elem[len(s.Elem)-1]
}
func (s *RecordStack)IsEmpty() bool {
return len(s.Elem) == 0
}
func hanoi3( N int) {
if N < 1 {
return
}
stack := NewRecordStack()
stack.Push(Record{
finish: false,
base: N,
from: "left",
to: "right",
other: "mid",
})
for !stack.IsEmpty() {
cur := stack.Pop()
if cur.base == 1 {
fmt.Println("Move 1 from",cur.from,"to",cur.to)
if !stack.IsEmpty() {
stack.Peek().finish = true
}
}else {
if !cur.finish {
stack.Push(cur)
stack.Push(Record{
finish: false,
base: cur.base-1,
from: cur.from,
to: cur.other,
other: cur.to,
})
}else {
fmt.Println("Move",cur.base,"from",cur.from,"to",cur.to)
stack.Push(Record{
finish: false,
base: cur.base-1,
from: cur.other,
to: cur.to,
other: cur.from,
})
}
}
}
}
func TestHanoi3(t *testing.T) {
hanoi3(3)
}
递归——汉诺塔问题
最新推荐文章于 2022-12-08 15:32:18 发布