【遞歸】—— 非空子集、全排列、合格括號、上樓梯、走方格

在這裏插入圖片描述1.上樓梯:每次只能走一步或兩步。

遞歸方程:f(n) = f(n-1) + f(n-2) + f(n-3)

臺階數 走法
1 1
2 2
3 4
4 7
f(n) f(n-1) + f(n-2) + f(n-3)

分別用遞歸與迭代實現:


public class temp3 {
	
	/*
	//way1:遞歸
	public static int fun(int n)
	{
		if(n<0)  return 0;
		if(n==1)   return 1;
		if(n==2)  return 2;
		if(n==3)   return 4;
		else
			return fun(n-1)+fun(n-2)+fun(n-3);
	}*/
	
	
	//way2:迭代
	public static int fun(int n)
	{
		int x1=1;
		int x2=2;
		int x3=4;
		if(n==1)  return 1;
		if(n==2)  return 2;
		if(n==3)  return 4;
		for(int i=n-3;i>0;i--)
		{
			int t=x1;
			x1 = x2;   //  x1=2
			x2 = x3;    //  x2=4
			x3 = x1+x2+t;  //x3 = 7	
		}
		
		return x3;
	}

	public static void main(String []args)
	{
		System.out.println(fun(2));
	}
    
}

2.機器人走方格:從左上角走到右下角,只能往右或向下走
遞歸方程:f(x,y) = f(x,y-1) + f(x-1,y)

走法
(1,1) 1
(1,2) 1
(1,3) 1
(2,1) 1
(3,1) 1
(1,j) 1
(i,1) 1
(2,2) 2
(2,3) 3
f(x,y) f(x,y-1) + f(x-1,y)

分別用遞歸與迭代實現:

public class temp4 {
	
	/*
	//way1:遞歸
	public static int fun(int x,int y)//x代表行,y代表列
	{
		if(x==1 || y==1)  return 1;
		else return fun(x-1,y)+fun(x,y-1);
	}
	*/

	//way2:迭代
	public static int fun(int x,int y)//x代表行,y代表列
	{
		//利用二維數組存儲
		int state[][] = new int[x+1][y+1];  //爲了方便理解多分配
		for(int j=1;j<=y;j++)
			state[1][j] = 1;
		for(int i=1;i<=y;i++)
			state[i][1] = 1;
		for(int i=2;i<=x;i++)
			for(int j=2;j<=y;j++)
				state[i][j] = state[i-1][j] + state[i][j-1];
		return state[x][y];
	}
	
	public static void main(String []args)
		System.out.println(fun(3,3));
}

3.合法括號:如輸出3個括號的組合方式:()()(),()(()),(())(),((())),(()()),不能重複
分別用遞歸與迭代實現:

import java.util.HashSet;
import java.util.Set;

public class temp1{
	     /*
	       //遞歸
		 	private Set<String> parenthesis(int n) {
				Set<String> s_n = new HashSet<>();
				if(n==1) {
					s_n.add("()");
					return s_n;
				}
				Set<String> s_n_1 = parenthesis(n-1); 
				for (String eofN_1:s_n_1) {   //for-each循環
					s_n.add("()"+eofN_1);
					s_n.add("("+eofN_1+")");
					s_n.add(eofN_1+"()");
				}
				return s_n;} 	
				*/ 
		 	//迭代
		 	private Set<String> parenthesis(int n) {
		 		Set<String> s_n = new HashSet<>();
		 		s_n.add("()");
		 		if(n==1)  return s_n;
		 		else{
		 			for(int i=2;i<=n;i++)
		 			{
		 			   Set<String> s_n_1 = new HashSet<>();
		 			for (String eofN_1:s_n) 
		 			{
		 				s_n_1.add("()"+eofN_1);
						s_n_1.add("("+eofN_1+")");
						s_n_1.add(eofN_1+"()");
		 			}
		 			s_n = s_n_1;  }
		 		return s_n;	
		 	}
		 	}
			public static void main(String []args){
			//調用非靜態方法要使用對象.方法的形式
			temp1 obj = new temp1();  //創建本類對象
		    Set<String> parenthesis = obj.parenthesis(3); //創建集合,調用方法
			System.out.println(parenthesis);
		}	
	}

4.非空子集遞歸實現:生成一個集合的全部子集,如{1,2}生成{{},{1},{2},{1,2}},
【有2的n次方個子集】

import java.util.Set;
import java.util.HashSet;

//注意點:要使用克隆clone(代碼行:27)。因爲對原集合做修改時,新集合也會隨之改變
public class temp2 {
	//遞歸法
	public  Set<Set<Integer>> get(int []A,int n)
	{
		return getts(A,n,n-1);
	}
	
	private Set<Set<Integer>> getts(int[] A,int n,int cur)
	{
		Set<Set<Integer>> newset = new HashSet<>();
		if(cur == 0){
			Set<Integer> one = new HashSet<>();  //空集合
			Set<Integer> last = new HashSet<>();  //有一個元素的集合
			last.add(A[0]);
			newset.add(one);
			newset.add(last);
			return newset;	
		}
		
		 Set<Set<Integer>> oldset = getts(A,n,cur-1);
		 for(Set<Integer> each:oldset) {
			 newset.add(each);
			 Set<Integer> clone = (Set<Integer>) ((HashSet)each).clone();       //克隆原來的集合
			 clone.add(A[cur]);
			 newset.add(clone);			 
		 }
		
		 return  newset;
	}
	
	public static void main(String []args)
	{
	    int []A = {1,2,3};
	    Set<Set<Integer>> newset = new temp2().get(A,A.length);
	    System.out.println(newset);
	}
}

5.全排列迭代實現:如”abc“得到[cba, bac, bca, cab, abc, acb]
【有n!個排列】

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

public class temp4 {
	
	public ArrayList<String> gets(String A){
		int n = A.length();
		ArrayList<String> res = new ArrayList<>();
		res.add(A.charAt(0) + ""); 
		//初始化; + ""是將A.charAt(0)這個字符轉換爲字符串
		
		for(int i=1;i<n;i++){
			String c = A.charAt(i)+"";
			ArrayList<String> res_new = new ArrayList<>();
			for(String str:res){
				String newStr;
				newStr = c + str;
				res_new.add(newStr);
				newStr = str + c;
				res_new.add(newStr);
				
				//加在中間
				for(int j=1;j<str.length();j++){
					newStr = str.substring(0,j)+c+str.substring(j);  
					res_new.add(newStr);
				  }
				}
			res = res_new;	
		}
		return res;
	}  
   public static void main(String []args){
	   String A = "abc";
	   ArrayList<String> res = new temp4().gets(A);
	   System.out.println(res);
   }
}
   

6.全排列回溯實現

import java.util.ArrayList;
import java.util.Arrays;

//全排列,回溯實現
//使用new String()將數組強制轉換爲字符串
public class temp5 {
  
	ArrayList<String> res = new ArrayList<>();
	public ArrayList<String> getPer(String A){
	
		char []arr = A.toCharArray();  //將字符串轉爲字符數組
		Arrays.sort(arr);
		getPerCore(arr,0);
 		return res;
	}

	private void getPerCore(char[] arr, int k) {
		if(k == arr.length){
			res.add(new String(arr));  //使用new String創建字符串
		}
		
		for(int i = k;i < arr.length;i++){
			swap(arr,k,i); //把後面的每個字符換到k位
			getPerCore(arr,k+1);
			swap(arr,k,i);  //回溯
		}
	}

	private void swap(char[] arr, int i, int j) {
		// TODO 自動生成的方法存根
		char tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}
	
	public static void main(String []args){
		System.out.println( new temp5().getPer("abc"));
	}
}

7.封閉形式的求解
(1)漢諾塔移動次數
遞歸公式: f(n) = 2f(n-1)+1;
直接求解:用(2的n次方)-1 ;n爲幾個盤子
(2)斐波那契數列第n項
在這裏插入圖片描述
(3)上樓梯
遞歸公式:f(n) = f(n-1)+f(n-2)+f(n-3)
直接求解:
ng)

堅持堅持。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章