递归的定义以及递归的示例(计算阶乘、计算斐波那契数、递归二分查找、回文串递归方法解决、汉诺塔问题、递归选择排序问题)
来源:互联网 发布:anaconda 改成python 2 编辑:程序博客网 时间:2024/04/27 19:13
1、关于递归
使用递归就是使用递归方法编程,递归方法就是直接或间接调用自己的方法。递归是一种针对使用简单的循环难以编程实现的问题,提供优雅解决方案的技术。
2、递归题目之:计算阶乘
数字n的阶乘可以递归的定义如下:0! = 1;(基本情况)n! = n * (n-1)!; n>0由于已经知道了0! = 1,而 1! = 1*0 !因此很容易计算求得1!。假设已知知道(n-1),使用n*(n-1)!就可以立即得到n!。这样,计算n!的问题就简化为计算(n-1)!。当计算 (n-1)!时,可以递归地应用这个思路直到n递减为0.
代码可以简单的写成:
if (n == 0){ return 1;}else{ return n*factorial(n-1);}
源代码为:
import java.util.*;public class Factorial { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入一个整数n,计算 n!"); int a = sc.nextInt(); System.out.println(factorial(a)); } public static long factorial(int n) { if (n == 0) return 1; else return n*factorial(n-1); }}
3、递归题目之:计算斐波那契数列
题目来源:http://ac.jobdu.com/problem.php?pid=1387
题目描述:
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。斐波那契数列的定义如下:
输入:
输入可能包含多个测试样例,对于每个测试案例,输入包括一个整数n(1<=n<=70)。
输出:
对应每个测试案例,输出第n项斐波那契数列的值。
样例输入:
3
样例输出:
2
源代码:
import java.util.*;public class Fibonacci { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int a = sc.nextInt(); System.out.println(fib(a)); } public static int fib(int n) { if (n == 0) return 0; else if (n ==1) return 1; else return fib(n-1) + fib(n-2); }}
4、递归题目之:汉诺塔问题
题目来源:http://ac.jobdu.com/problem.php?pid=1458
这个问题本质上是递归的,利用递归就能够找到一个自然、简单的解决方案。如果
不使用递归,解决这个问题将会非常的麻烦。从某种程度讲,递归提供了某种层次的抽象,这种抽象对用户隐藏迭代和其他细节。
在三个盘子的情况下,可以手动的找出解决方案。然而,当盘子数量较大时,即使是4个,这个问题还是非常的复杂的。幸运的是,这个问题的本身就具有递归的性质,可以得到直观的递归解决解法。
(1)、借助塔B将前 n-1 个盘子从 A 移到 C(2)、将盘子 n 从 A 移动到 B, (3)、借助塔 A 将 n-1 个盘子从 C 移动到 B。
题目描述:
输入盘子的个数,输出盘子移动的过程,一直到最后移动到最终的塔上。提示用户输入盘子个数,然后以调用递归的方法moveDisks来显示移动牌子的解决方案。
伪代码:
//下面的方法借助辅助塔auxTower 将 n 个盘子从原始塔 fromTower 移动到目标塔 toTower上void moveDisks(int n, char fromTower, char toTower, char auxTower)这个方法的算法可以描述如下:if (n == 1) //Stopping condition Move disk 1 from the fromTower to the toTowerelse{ moveDisks(n-1, fromTower, auxTower, toTower); Move disk n from the fromTower to the toTower; moveDisks(n-1, auxTower, toTower, fromTower);}
源代码:
import java.util.Scanner;public class TowerOfHanoi { /** * Main method */ public static void main(String[] args) { //Create a Scanner Scanner input = new Scanner(System.in); System.out.println("enter number of disks"); int n = input.nextInt(); //find the solution recursively System.out.println("the moves are:"); moveDisks(n, 'A', 'B', 'C'); } /** * The method for finding the solution to move n disks from * fromTower to toTower with auxTower */ public static void moveDisks(int n, char fromTower, char toTower, char auxTower) { if (n == 1)//stopping condition { System.out.println("move disk" +n+ "from" +fromTower+ "to" +toTower); } else { moveDisks(n-1, fromTower, auxTower, toTower); System.out.println("move disk" +n+ "from" +fromTower+ "to" +toTower); moveDisks(n-1, auxTower, toTower, fromTower); } }}
5、递归题目之:递归二分查找
使用二分查找的前提条件是数组元素必须已经排好序。二分查找法首先将关键字与数组中的元素进行比较,考虑下面三种情况:
情况一:如果关键字比中间元素小,那么只需要在前一半数组进行递归查找
情况二:如果关键字和中间元素相等,则匹配成功,查找结束
情况三:如果关键字比中间元素大,那么只需要在后一半数组进行递归查找
情况一和情况三都将查找返回将为一个更小的数列。而当匹配成功是,情况2就是一个基本情况。另外一个基本情况是查找完毕而没有一个成功的匹配。
public class RecursiveBinarySearch { public static int recursiveBinarySearch(int[] list, int key) { int low = 0; int high = list.length - 1; return recursiveBinarySearch(list, key, low, high); } private static int recursiveBinarySearch(int[] list, int key, int low, int high) { if (low < high) //the list has been exhausted without a match { return -low-1; } int mid = (low + high) / 2; if (key < list[mid]) return recursiveBinarySearch(list, key, low, mid - 1); else if (key == list[mid]) return mid; else return recursiveBinarySearch(list, key, mid + 1, high); } public static void main(String[] args) { int[] list = {1,2,3,4,5,6,99,888,999,1002,1003,1050,10006}; int key = 888; System.out.println(recursiveBinarySearch(list, key)); }}
6、递归题目之:回文串递归方法解决(两种解决方法)
回文串定义:
“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。
检查一个字符串是否是回文串的问题可以分为两个子问题:
(1)、检查字符串中的第一个字符和最后一个字符串是否相等
(2)、忽略两端的字符串之后检查子串的其余部分是否是回文串
解决方法一:
public class RecursivePalindromeUsingSubstring { public static boolean isPalindrome (String s) { if (s.length() <= 1) // base case return true; else if (s.charAt(0) != s.charAt(s.length() - 1)) // base case return false; else return isPalindrome(s.substring(1, s.length() - 1)); } public static void main(String[] args) { System.out.println("Is moon a palindrome?" +isPalindrome("moon")); System.out.println("Is noon a palindrome?" +isPalindrome("noon")); System.out.println("Is aba a palindrome?" +isPalindrome("aba")); System.out.println("Is ab a palindrome?" +isPalindrome("ab")); }}
解决方法二:(使用了递归辅助方法,下面的代码注释中会解释为什么第二种解法效率高一些)
package 递归;public class RecursivePalindrome { //在类RecursivePalindromeUsingSubstring中的isPalindrome方法要为每次调用创建一个新字符串,因此不够高效。 //为避免创建新字符串,可以使用low和high下表来表明子串的范围。这两个下标必须传递给递归方法。由于原始方法是isPalindrome(String s) //因此,必须产生一个新方法isPalindrome(String s, int low, int high)来接收关于字符串的额外信息,如下面的程序所示: //程序中定义了两个重载的isPalindrome方法。第一个方法isPalindrome(String s)检查一个字符串是否是回文串,而第二个方法 //isPalindrome(String s, int low, int high)检查一个子串 s(low..high)是否是回文串。第一个方法将low = 0 //和 high = s.length()-1的字符串s传递给第二个方法。第二个方法采用递归调用,检查不断缩减的子串是否是回文串。在递归设计中 //定义第二个方法来接收附加的参数是一个常用的技巧,这样的方法称为 递归辅助方法 public static boolean isPalindrome(String s) { return isPalindrome(s, 0, s.length()-1); } private static boolean isPalindrome(String s, int low, int high) { if (high <= low) //base case return true; else if (s.charAt(low) != s.charAt(high))//base case return false; else return isPalindrome(s, low+1, high-1); } public static void main(String[] args) { System.out.println("Is moon a palindrome?" +isPalindrome("moon")); System.out.println("Is noon a palindrome?" +isPalindrome("noon")); System.out.println("Is aba a palindrome?" +isPalindrome("aba")); System.out.println("Is ab a palindrome?" +isPalindrome("ab")); }}
7、递归题目之:选择排序
选择排序的思想是:先找到列表中的最小数,并和第一个元素交换。然后,再剩余的书中找到最小数,再将它和剩余列表中的第一个元素交换,这样的过程一直进行下去,直到列表中仅剩一个数为止。
这个问题可以分为两个子问题:
(1)、找出列表中的最小数,然后将它与第一个数进行交换。
(2)、忽略第一个数,对余下的较小一些的列表进行递归排序。
其中基本情况就是该列表中只包含一个数。
源代码:
public class RecursiveSelectionSort { public static void sort(double[] list) { sort(list, 0, list.length-1);//sort the entire list } private static void sort(double[] list, int low, int high) { if (low < high) { //find the smallest number and its index in list[low .. high] int indexOfMin = low;//假设下标为low的元素为最小值。 double min = list[low];//将下标为low的元素的值赋予min for (int i = low + 1; i <= high; i++) { if (list[i] < min) { min = list[i]; indexOfMin = i; } } //swap the smallest in list[low .. high] with list[low] list[indexOfMin] = list[low]; list[low] = min; //sort the remaining list[low+1 .. high] sort(list, low + 1, high); } } public static void main(String[] args) { double[] list = {1,99,2,65,51,78,23,99,101,33}; sort(list); for (int i = 0; i <= list.length; i++) { System.out.println(list[i]); } }}
- 递归的定义以及递归的示例(计算阶乘、计算斐波那契数、递归二分查找、回文串递归方法解决、汉诺塔问题、递归选择排序问题)
- 递归 --与三角数字,阶乘,变位字,汉诺塔问题,递归的二分查找法,归并排序
- 递归数的计算
- ;递归求和;递归计算阶乘
- 二分查找与斐波那契数递归与非递归的时间复杂度与空间复杂度
- 斐波那契数列和二分查找的算法(递归与非递归)
- 为什么用 递归 计算“阶乘”和“斐波那契数列”是不合适的?
- 为什么用 递归 计算“阶乘”和“斐波那契数列”是不合适的?
- 使用递归计算阶乘
- 递归计算阶乘
- 用递归计算阶乘
- 递归计算N阶乘
- 用递归计算阶乘!
- 非递归计算阶乘
- 递归计算阶乘
- 递归计算阶乘
- 递归算法计算阶乘
- 数据结构之用递归和非递归方法计算斐波那契数列的第n项
- gcc安装 error: cannot compute suffix of object files: cannot compile
- 每日一省————链表之栈的简单实现
- vim窗口的一些命令
- 【leetcode】String——Palindrome Pairs(336)
- 插入排序
- 递归的定义以及递归的示例(计算阶乘、计算斐波那契数、递归二分查找、回文串递归方法解决、汉诺塔问题、递归选择排序问题)
- kafka笔记
- BZOJ1272: [BeiJingWc2008]Gate Of Babylon
- objective-c 中new与alloc/init的区别
- dir函数:遍历文件名
- javase
- 插入排序、希尔排序、冒泡排序、快速排序、选择排序、堆排序、归并排序
- css3媒体查询
- gcc configure: error: Building GCC requires GMP 4.2+, MPFR 2.3.1+ and MPC 0.8.0+