1 递归
递归算法:在运行中不断调用自身;
理解:以参数的不同,把每次调用看成是调用不同的算法模块
构造方法不能使用递归
举一个n!的例子,看看算法是怎样执行的?
实例1:
package 测试集;
public class Demo2 {
public static void main(String[] args) {
/* 补充:构造方法不能使用递归
* public StringDemo(){
StringDemo();
*/
/**
*
*递归:方法嵌套
*
*方法递归:方法调用本身的一种现象
*
*三个条件:
* 1)需要定义个方法
* 2)方法必须有出口条件
* 3)必须有某一种规律
* */
/*需求:求5的阶乘
5! = 5 * 4 * 3 * 2 * 1 ;
5! = 5 * 4! ;*/
/**
* 1)明确返回值类型:int类型
* 参数类型:int类型的值
*
* 2)出口条件:
* if(n==1){
* return 1 ;
* }
*
* 3)要有规律
* if(n!=1){
* return n* 方法名(n-1);
* }
* */
//举例:n! public static int factory(int n){ if(n==1||n==0){ return 1 ; }else{ return n* factory(n-1) ; //5 * 4 * 3 * 2 *1 } } } 上述算法如何执行的?以n=3为例:
factory(3)→factory(2)→factory(1)-factory(2)→factory(2)→factory(3)
分两步:递归和回溯
说明:满足停止条件(即:递归到factory(1)),停止递归,开始回溯返回调用算法)并计算,从factory(1)返回到factory(2),计算2*factory(1)=2返回到factory(3);计算3*factory(2)=6结束递归。
特点:和一般的方法调用一样,算法的起始模块通常也是终止模块,通过参数值将"同一模块"的"不同次运行"进行区别后,理解递归函数执行过程!
实例2:
package 测试集;
import java.util.Scanner;
/*
1:兔子生育:
一对兔子(刚出生),从出生后第三个月起每个月都生一对兔子,小兔子长到三个月后每个月又生一对兔子
,假如兔子不死,问12个月后兔子的对数
分析:
月份(后): 1 2 3 4 5 6
兔子对数: 1 1 1+1(生) 1+1(生)+1(生) 1+1(生)+1(生)+2(生) 1+1(生)+1(生)+2(生)+3(生) ......
共: 1 1 2 3 5 8
规律:假设第n-2个月后的兔子为a[n-2];
第n-1月后的兔子为a[n-1];
则第n个月后兔子为a[n]=a[n-1]+a[n-2]
哎!这算不算近亲结婚!!!是不是有点像斐波那契数列?
注意:尽量选最大的类型(long int),以免数据溢出;这里只是简单测试选了int类型
*/
public class Demo2 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入月份:");
int month=sc.nextInt();
int rabitNum=rabitBrith(month);
System.out.println(month+"个月后兔子数量"+rabitNum);
}
public static int rabitBrith(int n){ //方法定义
if(n==1||n==2){
return 1 ; //出口条件
}else{
return rabitBrith(n-1)+rabitBrith(n-2) ; //规律
}
}
}
实例3:查询字符串的个数
package 测试集;
import java.util.Scanner;
public class Demo11 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输出待查询的字符串:");
StringBuffer s=new StringBuffer(sc.nextLine());
//待查询字符串内容:woaijavawozhenaijavawozhendeaijavawozhendehenaijavaxinbuxinwoaijavagun
System.out.println("需要查询的字符串:");
String s1=sc.nextLine();
//需要查询:java;
int count=0;
while(s.indexOf(s1)!=-1){
count++;
s.delete(s.indexOf(s1),s.indexOf(s1)+s1.length());
}
System.out.println("输入的字符串含java的个数:"+count);
}
}
实例4:二分查找
package 测试2;
/*
* 二分查找:
* 思想:就是将查找的键和子数组的中间键作比较;
* 如果被查找的键小于中间键,就在左子数组继续查找;
* 如果大于中间键,就在右子数组中查找;
* 否则中间键就是要找的元素;
* java设计:参数为数组(待查询)、键值(目标)
* 设计:如果未查询到该值,则返回:-1
* 如果查到,返回该索引
* 分析:由于每次查询后,范围缩小,多次查询(循环)
* 注意:循环结束条件
*
* */
public class Demo {
public static void main(String[] args) {
int[] arr = { 13, 24, 57, 69, 80 };// 数组静态初始化方式
System.out.println("二分法的结果:" + rank(arr, 24));// 查询到的情况
System.out.println("二分法的结果:" + rank(arr, 34));// 未查询到的情况
}
// 定义一个功能:二分查找(循环查找)
public static int rank(int[] arr, int key) {
int star = 0; // 起始
int end = arr.length - 1; // 终止
while (star <= end) { // 查找的结果:1)有此值 2)无此值
int mid = star + (end - star) / 2;// 中间值(下一次循环与键值进行比较)
if (arr[mid] > key) { // 中间值大于目标值,所以键值可能在左边;重新定义查找范围
end = mid - 1;
} else if (arr[mid] < key) { // 中间值小于目标值,所以键值可能在右边;重新定义查找范围
star = mid + 1;
} else { // 被查询到
return mid; // 查询到返回索引
}
}
return -1; // 如果没有查询到,此时(star>end),跳出while循环;返回值:-1
}
}