Violent recursion -- Hanoi Tower problem

Posted by nomadrw on Sun, 26 Dec 2021 14:04:52 +0100

Print the whole process of moving the n-layer Hanoi tower from the leftmost to the rightmost

Violent recursion is trying

1) The problem is transformed into a sub problem of the same kind of problem with reduced scale

2) There are explicit conditions (base case) that do not need to continue recursion

3) There is a decision-making process when the result of the subproblem is obtained

4) The solution of each subproblem is not recorded

In addition, if the solution of each sub problem is recorded as dynamic programming, it will be discussed in subsequent articles.

Recursive Method

Suppose there are three columns, left, middle and right, which are subdivided into the following three steps:

1) Turn 1~N-1 layers of discs from left - > middle (large problems, which need to be further divided into small problems)

2) Turn the nth layer disc from left to right (base case)

3) Turn 1~N-1 layers of disks from the middle to the right (large problems need to be divided into small problems)

Improved version of recursive method

If we forget the left, middle and right of the columns, mark the three columns as from, to and other. What we achieve is to subdivide all discs (N layers in total) from from - > to into three steps:

1) Turn 1~N-1 layers of disks from from - > other (large problems need to be further divided into small problems)

2) Change the disc of the nth layer from from - > to (base case, which can be printed directly)

3) Turn 1~N-1 layers of discs from other - > to (large problems, which need to be further divided into small problems)

There seems to be no improvement, because the three steps are subdivided and recursive, but the key is to forget the left, middle and right order of the columns. Only three variables are required, and the code can be much less.

summary

Hanoi Tower problem also has a non recursive solution, because any recursion can be changed into non recursion, and you only need to design your own stack. However, bloggers personally think that the recursive method of Hanoi tower is easier to understand and implement than non recursive method. It is troublesome to design stack by non recursive method. Bloggers have not understood it yet, so they only attach code. If you understand later, you can add it, 😄

Attach the complete code

package com.harrison.class12;

import java.util.Stack;

public class Code01_Hanoi {
	public static void leftToRight(int n) {
		if(n==1) {
			System.out.println("move 1 from left to right");
			return ;
		}
		leftToMid(n-1);
		System.out.println("move "+ n +" from left to right");
		midToRight(n-1);
	}
	
	public static void leftToMid(int n) {
		if(n==1) {
			System.out.println("move 1 from left to mid");
			return ;
		}
		leftToRight(n-1);
		System.out.println("move "+ n +" from left to mid");
		rightToMid(n-1);
	}
	
	public static void midToRight(int n) {
		if(n==1) {
			System.out.println("move 1 from mid to right");
			return ;
		}
		midToLeft(n-1);
		System.out.println("move "+ n +" from mid to right");
		leftToRight(n-1);
	}
	
	public static void midToLeft(int n) {
		if(n==1) {
			System.out.println("move 1 from mid to left");
			return ;
		}
		midToRight(n-1);
		System.out.println("move "+ n +" from mid to left");
		rightToLeft(n-1);
	}
	
	public static void rightToLeft(int n) {
		if(n==1) {
			System.out.println("move 1 from right to left");
			return ;
		}
		rightToMid(n-1);
		System.out.println("move "+ n +" from right to left");
		midToLeft(n);
	}
	
	public static void rightToMid(int n) {
		if(n==1) {
			System.out.println("move 1 from right to mid");
			return ;
		}
		rightToLeft(n-1);
		System.out.println("move "+ n +" from right to mid");
		leftToMid(n-1);
	}
	
	public static void hanoi1(int n) {
		leftToRight(n);
	}
	
	public static void f(int n,String from,String to,String other) {
		if(n==1) {
			System.out.println("move 1 from "+ from + " to " + to);
		}else {
			f(n-1, from, other, to);
			System.out.println("move " + n + " from " +from +" to "+to);
			f(n-1, other,to,from);
		}
	}
	
	public static void hanoi2(int n) {
		if(n>0) {
			f(n, "left", "right", "mid");
		}
	}
	
	public static class Record {
		public boolean finish1;
		public int base;
		public String from;
		public String to;
		public String other;

		public Record(boolean f1, int b, String f, String t, String o) {
			finish1 = false;
			base = b;
			from = f;
			to = t;
			other = o;
		}
	}

	public static void hanoi3(int N) {
		if (N < 1) {
			return;
		}
		Stack<Record> stack = new Stack<>();
		stack.add(new Record(false, N, "left", "right", "mid"));
		while (!stack.isEmpty()) {
			Record cur = stack.pop();
			if (cur.base == 1) {
				System.out.println("Move 1 from " + cur.from + " to " + cur.to);
				if (!stack.isEmpty()) {
					stack.peek().finish1 = true;
				}
			} else {
				if (!cur.finish1) {
					stack.push(cur);
					stack.push(new Record(false, cur.base - 1, cur.from, cur.other, cur.to));
				} else {
					System.out.println("Move " + cur.base + " from " + cur.from + " to " + cur.to);
					stack.push(new Record(false, cur.base - 1, cur.other, cur.to, cur.from));
				}
			}
		}
	}
	
	public static void main(String[] args) {
		int n=3;
		hanoi1(n);
		System.out.println("=======================");
		hanoi2(n);
		System.out.println("=======================");
		hanoi3(n);
		System.out.println("=======================");
	}
}

Topics: Algorithm