算法:递归
Posted nuist__NJUPT
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法:递归相关的知识,希望对你有一定的参考价值。
* 递归:方法自己调用自己
* 步骤:找重复:将原问题转换成子问题,找变化量:作为参数,找边界:作为出口
* 学习方法:1-循环改递归,经典递归,大量练习,总结规律,最后挑战高难度递归
1. 键盘输入一个正整数,求该正整数的阶乘。
算法思路:找重复:f(n)=n*f(n-1);找参数n,找边界:n==0时候为f(n)=1。
import java.util.Scanner;
/**
* 键盘输入一个正整数,求该正整数的阶乘
*/
public class FactorialDemo {
public static int factorial(int n){
if(n == 0){
return 1 ;
}
return n * factorial(n - 1) ;
}
public static void main(String[] args){
Scanner input = new Scanner(System.in) ;
int number = input.nextInt() ;
System.out.println(factorial(number)) ;
}
}
求任意整数的阶乘,使用BigInteger对象,可以实现任意大的整数的阶乘。
import java.math.BigInteger;
import java.util.Scanner;
public class Factorial {
public static BigInteger factorial(long n){
BigInteger result = new BigInteger("1") ;
for(int i=2; i<=n; i++){
result = result.multiply(new BigInteger(i + "")) ;
}
return result ;
}
public static void main(String[] args){
Scanner input = new Scanner(System.in) ;
long n = input.nextLong() ;
System.out.println(factorial(n)) ;
}
}
2. 递归实现:键盘输入i和j,i<=j,打印从i到j的所有元素 。
算法思想:找重复:f(i,j)=i->f(i+1,j);找变化:i作为参数,找出口:i>j结束递归。
import java.util.Scanner;
public class PrintFromIToJ {
public static void printFromIToJ(int i, int j){
if(i > j){ //边界出口
return ;
}
System.out.println(i) ; //i为变化的参数
printFromIToJ(i+1,j) ; //重复的部分
}
public static void main(String[] args){
Scanner input = new Scanner(System.in) ;
int i = input.nextInt() ;
int j = input.nextInt() ;
printFromIToJ(i,j) ;
}
}
3.递归实现求数组的所有元素之和。
算法思路:1-找重复:从第一个开始叠加; 2-找变换:变化的量作为参数,begin ; 3-找边界:当begin等于arr.length-1时,为递归出口。
public class ArraySum {
public static int getArraySum(int [] arr, int begin){
if(begin == arr.length-1){
return arr[begin] ;
}
return arr[begin] + getArraySum(arr,begin+1) ;
}
public static void main(String[] args){
int [] arr = {1,2,3,4,5,6,7,8,9,10} ;
System.out.println(getArraySum(arr,0)) ;
}
}
4.递归实现字符串的翻转。
算法思想:找重复:先打印最后一个字符,后面字符递归;找变化:字符串长度作为参数;找边界:当最后一个元素为字符串的第一个字符的时候为出口。
import java.util.Scanner;
public class Reverse {
public static String reverse(String src, int end){
if(end == 0){
return src.charAt(0) + "" ;
}
return src.charAt(end) + reverse(src,end - 1) ;
}
public static void main(String[] args){
Scanner input = new Scanner(System.in) ;
String src = input.next() ;
System.out.println(reverse(src,src.length()-1)) ;
}
}
5.递归和迭代实现求斐波那契数列的第n项及前n项和。
算法思想:找重复:f(n) = f(n-1) + f(n - 2) ,分解为多个小规模子问题 ;找变化:参数n ;找边界:当n==1或n==2时候为出口。
import java.util.Scanner;
public class Fibonacci {
public static int fibonacci(int n){
if(n == 1 || n == 2){
return 1 ;
}
return fibonacci(n - 1) + fibonacci(n - 2) ;
}
public static void main(String[] args){
Scanner input = new Scanner(System.in) ;
int number = input.nextInt() ;
System.out.println("斐波那契数列的第" + number +"项为:" + fibonacci(number) ) ;
int sum = 0 ;
for(int i=1; i<=number; i++){
sum += fibonacci(i) ;
}
System.out.println("斐波那契数列的前" + number + "项和为:" + sum) ;
}
}
6.递归实现求两个正整数的最大公约数和最小公倍数。
算法思想:找重复:f(m,n)=f(n,m%n);找变化:m,n;找边界:n等于0时候,为出口
m*n=最大公约数*最小公倍数
import java.util.Scanner;
public class GcdLcm {
public static int gcd(int m, int n){
if(n == 0){
return m ;
}
return gcd(n,m % n) ;
}
public static void main(String[] args){
Scanner input = new Scanner(System.in) ;
int m = input.nextInt() ;
int n = input.nextInt() ;
System.out.println("最大公约数为:" + gcd(m,n)) ;
System.out.println("最小公倍数为:" + (m * n) / gcd(m,n)) ;
}
}
7. 插入排序的递归实现。
算法思想:找重复:对数组的k-1个元素进行排序,划分成子问题,将第k个元素插入;找变化:k作为参数;找边界:当k等于0时为出口。
public class InsertSortDemo {
public static void insertSort(int [] arr, int k){
if(k == 0){
return ;
}
insertSort(arr,k-1) ;
int x = arr[k] ;
int index = k - 1 ;
while(x < arr[index] && index >= 0){
arr[index+1] = arr[index];
index -- ;
if(index < 0){
break ;
}
}
arr[index+1] = x ;
}
public static void main(String[] args){
int [] arr = {2,1,5,4,3,9,7,8,0} ;
insertSort(arr,arr.length-1) ;
for(int i=0; i<arr.length; i++){
System.out.print(arr[i] + " ") ;
}
}
}
8.汉诺塔游戏,将N个盘子从A移动到B,C为辅助,保证盘子N在最低部,1在最上部。
算法思想:将1-N-1个盘子从A移动到C,将第N个盘子从A移动到B,将1-N个盘子从C移动到B
public class HanoiTower {
public static void hanoiTower(int N, String from, String to, String help) {
if (N == 1) {
System.out.println("将第" + N + "个盘子从" + from + "移动到" + to);
return;
}
hanoiTower(N - 1, from, help, to);
System.out.println("将第" + N + "个盘子从" + from + "移动到" + to);
hanoiTower(N - 1, help, to, from);
}
public static void main(String[] args){
hanoiTower(3, "A", "B", "C") ;
}
}
9.二分查找的递归解法。
算法思想:找重复:关键字与中间元素进行比较,每次缩小查询范围。找变化:low和high在不断的变化,故作为参数。找边界:当low>high时候为出口。
public class BinarySearch {
public static int binarySearch(int [] arr, int low, int high, int key){
int mid = (low + high) >>> 1 ;
if(low > high){ //出口
return -1 ;
}
if(key > arr[mid]){
return binarySearch(arr,mid+1, high, key) ;
}
else if(key < arr[mid]){
return binarySearch(arr, low, mid-1, key) ;
}
else{
return mid ;
}
}
public static void main(String[] args){
int [] arr = {1,2,3,4,6,7,8,9} ;
System.out.println(binarySearch(arr,0,arr.length-1, 7)) ;
}
}
10.小白上楼梯。小白正在上楼梯,楼梯有n阶台阶,键盘输入n,小白一次可以上1阶,2阶或者3阶, 实现一个方法,计算小白有多少种走完楼梯的方式,打印输入方式种数?
import java.util.Scanner;
public class ClimbStair {
public static int f(int n){
if(n == 1){
return 1 ;
}
if(n == 2){
return 2 ;
}
if(n == 3){
return 4 ;
}
return f(n-1) + f(n-2) + f(n-3) ;
}
public static void main(String[] args){
Scanner input = new Scanner(System.in) ;
int n = input.nextInt() ;
System.out.println(f(n)) ;
}
}
11.在有空字符串的有序字符串数组中查找 ,有个排序后的字符串数组,其中散布着一些空字符串, 编写一个方法,找出给定字符串(肯定不是空字符串)的索引。
算法思想:对于有序字符串数组的查找,可以采用二分查找的思想,将目标值与中间值比较,不断折半,缩小查找范围,直至查找结束。
public class Search {
public static int search(String [] arr, String target){
int low = 0 , high = arr.length-1 ;
while(low <= high){
int mid = (low + high) >>> 1 ;
while(arr[mid].equals("")){
mid ++ ;
if(mid > high){
return -1 ;
}
}
if(arr[mid].compareTo(target) > 0){
high = mid - 1 ;
}
else if(arr[mid].compareTo(target) < 0){
low = mid + 1 ;
}
else{
return mid ;
}
}
return -1 ;
}
public static void main(String[] args){
String [] arr = {"a", "", "ac", "", "ad", "", "b", "", "ba"} ;
System.out.println(search(arr,"ba")) ;
}
}
12.最长连续递增子序列(部分有序) ,(1925734680)中最长的递增子序列为(3468)
算法思想:采用双指针,记录移动的位置以及最大连续递增序列的长度。
public class SubDemo {
public static String sub(String s){
int low = 0, high = 1, length = 0, maxLength = 0, end = 0 ;
while(low != s.length()-1){
if(s.charAt(high) > s.charAt(low)){
low ++ ;
high ++ ;
length ++ ;
if(length > maxLength){
maxLength = length ;
end = low ;
}
}
else{
low ++ ;
high ++ ;
length = 0 ;
}
}
String result = "" ;
for(int i=end-maxLength; i<=end; i++){
result += s.charAt(i) ;
}
return result ;
}
public static void main(String[] args){
String s = "1925734680" ;
System.out.println(sub(s)) ;
}
}
13.递归求解整数a的n次整数幂。
算法思路:先算偶数次方,再递归算奇数次方。
import java.util.Scanner;
public class GetPowerDemo {
public static int pow(int a, int n){
int ex = 1, res = a;
if(n == 0){
return 1 ;
}
while((ex<<1) <= n){
res *= pow(a,ex) ;
ex <<= 1 ;
}
return res * pow(a,n-ex);
}
public static void main(String[] args){
Scanner input = new Scanner(System.in) ;
int a = input.nextInt() ;
int n = input.nextInt() ;
System.out.println(pow(a,n)) ;
}
}
以上是关于算法:递归的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript - 代码片段,Snippets,Gist
有人可以解释啥是 SVN 平分算法吗?理论上和通过代码片段[重复]