递归方法解决:
public static long getFactorial1(int n){
//下面的if为明确的不再递归的条件
if(n==1){
//不再递归之后实现的操作
return 1L;
}
//将问题转化为规模缩小了的同类问题的子问题
return (long)n*getFactorial1(n-1);
}
非递归方法:
public static long getFactorial2(int n){
long result = 1L;
for(int i = 1;i<=n;i++){
result *= i;
}
return result;
}
三个竹竿,最开始最左边有n层汉诺塔,要将其全部移动到最右边的竹竿上,在移动的过程中只能小压大,不能大压小。
现在分为三个,from,to,help。移动的全部过程分为:
public static void process(int N,String from,String to,String help){
if(N==1){
System.out.println("move 1 from" + from + " to " + to;
}else{
process(N-1,from,help,to);
System.out.println("move" +N +"from " +from + "to" + to);
process(N-1,help,to,from);
}
}
以上的代码是整个程序的整体思路,也可以将过程详细化,将整体分为六个过程,然后彼此嵌套。
尝试过程:字符串共有多少长度,对于每一位,都有两个决策,所以总的可能性2^N,这是一道简单的高中数学排列组合问题,所以可以进行要不要的递归,最终实现所有的情况。
public static void printAllSub(char[] Str,int i,String res){
if(i == str.length){
System.out.println(res);
return;
}
//不要当前字符
printAllSub(str,i+1,res);
//要当前字符
printAllSub(str,i+1,res+String.valueof(str[i]));
}
对于每次递归,都走要不要当前字符两条路,从而可以实现打印所有的子序列,如果题目进行修改,不包括空字符串的haul,则此时可以进行空字符串的判断,进行删除。
最开始是A,这是第一批,之后每年增加1,第二年出生的牛增加三年可以生小牛,则可以设立新出生的牛一个i=3的数值,每过一年则i–,当i<=0时则第二年加上该牛的两倍,同时让该数目的牛重新设置i,这是我自己的思路。
但是通过数值的变化可以发现数目满足一个规律,F(n) = F(n-1)+F(n-3)。今年的牛等于上一年的牛的数目加上三年前牛的数目。
由暴力版本改成动态规划
自己思路:这道题可以按照上方的打印全部字符串进行计算,将结果存放到一个小跟堆中,最后返回小根堆的根就是最小路径和。非常暴力
左神尝试版本:
public static int walk(int[][] matrix,int i,int j){
if(i==matrix.length-1 && j == matrix[0].length-1){
return matrix[i][j];
}
if(i == matrix.length-1){
return matrix[i][j] + walk(matrix,i,j+1);
}
if(j == matrix[0].length-1){
return matrix[i]ij]+ walk(matrix,i+1,j);
}
int right = walk(matrix,i,j+1);//右边位置到右下角的最短路径和
int down = walk(matrix,i+1,j);//下边位置到右下角最短路径和
return matrix[i][j] + Math.min(right,down);
}
上述暴力递归中存在很多的重复计算(一个先向下再像右,一个先向右再向下,此时都会到(1,1)位置,上述题目会存在重复计算)
当发现递归中存在重复状态,并且重复状态和与到达他的路径没有关系的时候,可以将递归改成动态规划
动态规划要求点无后效性,也就是说当给出了参数之后,结果唯一。如果给定参数之后,返回值不是唯一确定的时候,此时成为有后效性。(比如要求记录路径的时候,路径方式不一定唯一)
动态规划:
对于这道题目,可以按照上述代码,可以首先将最后一行中到右下角的距离挨个计算出,此时为最后一行的点到右下角的距离。也要先将最后一列中到右下角的距离挨个算出,为最后一列的点到右下角的距离。此时可以从右到左,再从下到上,就可以 计算出整个距离。
暴力递归改成动态规划的步骤:
这道题是作为动态规划的练习题,可以发现题目的求解过程跟上一道题类似.
思路:设置sum,对于每一个数组中的数字,都可以进行判断,是否要当前的数字,分为两种情况,然后最后和aim相比较。如果发现最后的结果中存在aim,则返回true。
public static boolean isSum(int[] arr,int i,int sum,int aim){
if(i == arr.length){
return sum = aim;
}
return isSum(arr,i+1,sum,aim) || isSum(arr,i+1,sum+arr[i],aim);
}