函数自己调用自己,方法自己调用自己
确定能否使用递归求解
推导出父问题和子问题的关系,以及递归的结束条件
注:
- 深入到最里层叫递
- 从最里层出来叫归
- 在递的过程中,外层函数的局部变量(以及方法参数)并未消失,归的时候还可以用
1.阶乘
java
package algorithm.datastructure.recursion;
public class Factorial {
public static int factorial(int n){
if (n == 1){
return 1;
}
return n * factorial(n-1);
}
public static void main(String[] args){
int res = factorial(5);
System.out.println(res);
}
}
2.反向输出字符串
java
package algorithm.datastructure.recursion;
public class ReversePrintString {
public static void reversePrint(String str, int n){
if (n == str.length()) {
return;
}
reversePrint(str, n+1);
System.out.println(str.charAt(n)); // 在归的过程中打印字符
}
public static void main(String[] args){
reversePrint("Hello World",0);
}
}
java
package algorithm.datastructure.recursion;
public class ReversePrintString {
public static void reversePrint(String str, int n){
if (n == -1){
return;
}
System.out.println(str.charAt(n)); // 在递的过程打印字符
reversePrint(str, n - 1);
}
public static void main(String[] args){
String str = "Hello World";
reversePrint(str,str.length() - 1);
}
}
3.递归实现二分查找
java
package algorithm.datastructure.recursion;
public class RecursionBinarySearch {
public static int binarySearch(int[] arr, int target, int lo, int hi){
if (lo > hi){
return -1;
}
int mid = (lo + hi) >>> 1;
if (target < arr[mid]){
return binarySearch(arr, target, lo, mid - 1);
} else if (arr[mid] < target){
return binarySearch(arr, target, mid + 1, hi);
} else {
return mid;
}
}
public static void main(String[] args){
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
System.out.println(binarySearch(arr, 8, 0, arr.length - 1));
}
}
4.递归实现冒泡排序
循环版本:
java
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int[] arr = new int[n];
for(int i = 0; i < n; i++){
arr[i] = scan.nextInt();
}
scan.close();
bubbleSort(arr);
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i] + " ");
}
}
public static void bubbleSort(int[] arr){
int n = arr.length;
for(int i = 0; i < n - 1 ; i++){
for(int j = 0; j < n - 1 - i; j++){
if(arr[j] > arr[j + 1]){
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
}
}
递归版本:
java
package algorithm.datastructure.recursion;
public class RecursionBubbleSort {
public static void bubbleSort(int[] arr, int n){
if(n == 0){
return; // 如果未排序的元素个数为0,则表示已经排好序了
}
for(int i = 0; i < n; i++){
if(arr[i] > arr[i + 1]){
int temp = arr[i+1];
arr[i + 1] = arr[i];
arr[i] = temp;
}
}
bubbleSort(arr, n - 1); // 递, 每次比较后,未排序的元素个数减1
}
public static void main(String[] args){
int[] arr = {5, 4, 3, 2, 1};
bubbleSort(arr, arr.length - 1);
for(int e: arr){
System.out.print(e + " ");
}
}
}
改进的递归版本1:
java
package algorithm.datastructure.recursion;
public class RecursionBubbleSort {
public static void bubbleSort(int[] arr, int n){
if(n == 0){
return;
}
boolean flag = false;
for(int i = 0; i < n; i++){
if(arr[i] > arr[i + 1]){
flag = true;
int temp = arr[i+1];
arr[i + 1] = arr[i];
arr[i] = temp;
}
}
if(!flag){
return; // 若没有发生交换,则说明数组已经有序,递归结束 注意:Java中没有"全局变量"这个概念
}
bubbleSort(arr, n - 1); // 递, 每次比较后,未排序的元素个数减1
}
public static void main(String[] args){
int[] arr = {5, 4, 3, 2, 1};
bubbleSort(arr, arr.length - 1);
for(int e: arr){
System.out.print(e + " ");
}
}
}
Java变量作用域规则:
- 局部变量:在方法内声明,只能在该方法内访问
- 实例变量:在类中声明,在对象的所有方法中可访问
- 类变量:用 static 修饰,在整个类中可访问
改进的递归版本2:
java
package algorithm.datastructure.recursion;
public class RecursionBubbleSort {
public static void bubbleSort(int[] arr, int n) {
if (n == 0) {
return;
}
int x = 0;
for (int i = 0; i < n; i++) {
if (arr[i] > arr[i + 1]) {
int temp = arr[i + 1];
arr[i + 1] = arr[i];
arr[i] = temp;
x = i; // x用来记录每次发生交换时较大元素的位置,一个for循环结束后,x位置后面的元素就是有序的了,因此下次递归时,到x位置结束
}
}
bubbleSort(arr, x); // 但是如果该次for循环没有发生交换,x的值为0,就可以退出递归了
}
public static void main(String[] args){
int[] arr = {5, 4, 3, 2, 1};
bubbleSort(arr, arr.length - 1);
for(int e: arr){
System.out.print(e + " ");
}
}
}