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)
直接求解:
堅持堅持。。