用栈来求解hanoi塔问题

题目来源:程序员算法面试指南,牛客网出品;

第一种解法:递归法;

 1 //解法一:用递归法;
 2     public static int hanoi(int n, String left, String mid, String right){
 3         if(n<1){
 4             return 0;
 5         }
 6         return process(n, left, mid, right, left, right);
 7     }
 8     
 9     public static int process(int n, String left, String mid, String right, String from, String to){
10         //n=1时,结束条件
11         if(n==1){
12             //from或to有一个是mid,只需移动1次
13             if(from.equals(mid) || to.equals(mid)){
14                 System.out.println("Move 1 from "+from+" to "+to);
15                 return 1;
16             } else{
17                 //from和to都不是mid,需移动2次
18                 System.out.println("Move 1 from "+ from + " to "+mid);
19                 System.out.println("Move 1 from "+ mid + " to " + to);
20                 return 2;
21             }
22         } 
23         // n > 1,
24         // from 或 to 有一个是mid, 只需移动一次;
25         if(from.equals(mid)||to.equals(mid)){
26             String another = (from.equals(left)||to.equals(left))? right : left;
27             int part1 = process(n-1, left, mid, right, from, another);
28             int part2 = 1;
29             System.out.println("Move " + n +" from "+from+" to "+ to);
30             int part3 = process(n-1, left, mid, right, another, to);
31             return part1 + part2 + part3;
32         }else{
33             // from、to都不是mid, 共需移动5步
34             int part1 = process(n-1, left, mid, right, from, to);
35             int part2 = 1;
36             System.out.println("Move "+ n +" from "+from +" to "+mid);
37             int part3 = process(n-1, left, mid, right, to, from);
38             int part4 = 1;
39             System.out.println("Move "+ n +" from "+mid +" to "+to);
40             int part5 = process(n-1, left, mid, right, from, to);
41             return part1 + part2 + part3 + part4 + part5;
42         }
43     }

第二种解法:用栈模拟

 1 //第二种解法
 2     //用栈模拟
 3     public static int hanoi(int n){
 4         Stack<Integer> LS = new Stack<Integer>();
 5         Stack<Integer> MS = new Stack<Integer>();
 6         Stack<Integer> RS = new Stack<Integer>();
 7         
 8         for(int i=n; i>0; i--)
 9             LS.push(i);
10         
11         int counter = 1;    //记录移动次数
12         int last_step = 1;    //记录前一次移动,1:从左边移到中间,2:从中间移到左边,3:从中间移动到右边,4:从右边移动到中间
13         MS.push(LS.pop());    //第一次,必须是左边往中间移动
14         System.out.println("Move 1 from left to mid");
15         
16         while(RS.size() != n){
17             for(int this_step=1; this_step<5; this_step++){    //步骤循环,判断哪种是正确的移动步骤,每次只有一种正确移法;
18                 //当前步,不能跟上一步重复,也不能跟上一步相反(浪费移动步数)
19                 if(this_step == last_step ||
20                         this_step + last_step == 3 || this_step + last_step == 7)
21                     continue;
22                 switch (this_step){
23                 case 1: //从左边移动到中间
24                     if(LS.empty()) break;    //如果左边栈是空的,则不能进行移动
25                     if(MS.empty() || LS.peek() < MS.peek()){    //如果中间栈为空,则不需要判断后边的,否则MS.peek()会报错
26                         MS.push(LS.pop());
27                         System.out.println("Move " + MS.peek() + " from left to mid.");
28                         counter++;
29                         last_step = this_step;    //当前步在下一次移动时成为上一步
30                     }
31                     break;
32                 case 2:
33                     if(MS.empty()) break;
34                     if(LS.empty() || MS.peek() < LS.peek()){
35                         LS.push(MS.pop());
36                         System.out.println("Move " + LS.peek() + " from mid to left.");
37                         counter ++;
38                         last_step = this_step;
39                     }
40                     break;
41                 case 3:
42                     if(MS.empty()) break;
43                     if(RS.empty() || MS.peek() < RS.peek()){
44                         RS.push(MS.pop());
45                         System.out.println("Move "+ RS.peek() + " from mid to right.");
46                         counter ++;
47                         last_step = this_step;
48                     }
49                     break;
50                 case 4:
51                     if(RS.empty()) break;
52                     if(MS.empty() || MS.peek() > RS.peek()){
53                         MS.push(RS.pop());
54                         System.out.println("Move "+ MS.peek() + " from right to mid.");
55                         counter++;
56                         last_step = this_step;
57                     }
58                     break;
59                 default:
60                     System.out.println("step choice error!");
61                 }
62             }
63         }
64         return counter;
65     }

 

posted @ 2017-09-15 22:36  Apollo_zhanghongbo  阅读(423)  评论(0编辑  收藏  举报