目录
什么是递归?
是一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
递归有三个要素:
- 有边界条件
- 有递归前进段
- 有递归返回段
当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
递归(recursion)与迭代(iterate)的区别:
迭代是人,递归是神
递归是不断地深层调用函数,直到函数有返回才会逐层的返回。递归编程所体现的思想正是人们追求简洁、将问题交给计算机,以及将大问题分解为相同小问题从而解决大问题的动机。
迭代大部分时候需要人为的对问题进行剖析,将问题转变为一次次的迭代来逼近答案。迭代不像递归一样对堆栈有一定的要求,另外一旦问题剖析完毕,就可以很容易的通过循环加以实现。
例:斐波那契数列
package yrwan07;
import org.junit.Test;
/**
* 递归的应用——斐波那契数列
*
* @author Wyran
*
*/
public class Fibonacci {
@Test
public void FibonacciTest() {
System.out.println(getNumber(5));
}
public int getNumber(int n) {
if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
} else {
return getNumber(n - 1) + getNumber(n - 2);
}
}
}
例:有序数组的二分法查找
package yrwan07;
import org.junit.Test;
/**
* 递归的应用——二分法在有序数组中查找
*
* @author Wyran
*
*/
public class BinarySearch {
@Test
public void binarySearchTest() {
int[] arr = { 10, 11, 12, 16, 18, 23, 29, 33, 48, 54, 57, 68, 77, 84, 98 };
System.out.println(binarySearch(arr, 23, 0, arr.length - 1));
}
/**
*
* @param arr 有序数组
* @param target 待查找值
* @param left 数组最小下标
* @param right 数组最大下标
* @return 待查值的下标
*/
public int binarySearch(int[] arr, int target, int left, int right) {
int mid = (left + right) / 2;
if (target == arr[mid]) {
return mid;
} else if (left > right) {
return -1;
} else {
if (arr[mid] > target) {
return binarySearch(arr, target, left, mid - 1);
}
if (arr[mid] < target) {
return binarySearch(arr, target, mid + 1, right);
}
}
return -1;
}
}
例:汉诺塔问题
package yrwan07;
import org.junit.Test;
/**
* 递归的应用——汉诺塔问题
*
* @author Wyran
*
*/
public class HanoiTower {
@Test
public void moveTest(){
move(3, "A", "B", "C");
}
/**
*
* @param num 移动的盘子数
* @param from 初始塔
* @param temp 中间塔
* @param to 目标塔
*/
public void move(int num, String from, String temp, String to) {
if (num == 1) {
System.out.println("将" + num + "号盘从" + from + "移动到" + to);
} else {
move(num - 1, from, to, temp);
System.out.println("将" + num + "号盘从" + from + "移动到" + to);
move(num - 1, temp, from, to);
}
}
}
例:归并排序
package yrwan07;
import java.util.Arrays;
import org.junit.Test;
/**
* 递归的应用——归并排序
*
* @author Wyran
*
*/
public class MergeSort {
@Test
public void mergeSortTest() {
int[] arr = { 1, 8, 9, 6, 4, 3, 9, 15, -1 };
int[] result = mergeSort(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(result));
}
/**
* 归并排序递归部分
*
* @param arr 待排序数组
* @param left 开始排序的下标
* @param right 结束排序的下标
* @return 排序好的数组
*/
public int[] mergeSort(int[] arr, int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
merge(arr, left, mid, right);// 合并
}
return arr;
}
/**
* 归并排序合并部分
*
* @param arr 待排序数组
* @param left 左数组的开始下标
* @param mid 左数组的结束下标
* @param right 右数组的结束下标
*/
public void merge(int[] arr, int left, int mid, int right) {
int[] temp = new int[right - left + 1];
int i = left;// 左数组的开始下标
int j = mid + 1;// 右数组的开始下标
int num = 0;
while (i <= mid && j <= right) {
if (arr[i] < arr[j]) {
temp[num++] = arr[i++];
} else {
temp[num++] = arr[j++];
}
}
while (i <= mid) {
temp[num++] = arr[i++];
}
while (j <= right) {
temp[num++] = arr[j++];
}
for (int k = 0; k < temp.length; k++) {
arr[k + left] = temp[k];
}
}
}
例:背包问题
package yrwan07;
/**
* 递归的应用——背包问题
*
* @author Wyran
*
*/
public class Knapsack {
private int[] weights; // 物品重量
private boolean[] select;// 物品是否选择
private boolean flag = false; // 结束递归的判断
public Knapsack(int[] arr) {
this.weights = arr;
select = new boolean[arr.length];
}
/**
*
* @param target 背包剩余可容纳重量
* @param index 尝试放入下标为index的物品
*/
public void knapsack(int target, int index) {
if (flag) {
return;
}
// 如果剩余可容纳为0则说明已成功
if (target == 0) {
flag = true;// 结束递归
for (int i = 0; i < index; i++) {
if (select[i] == true) {
System.out.print(weights[i] + " ");
}
}
return;
}
// 未找到方法
if (target < 0 || index >= weights.length) {
return;
}
// 进行递归
// 尝试放入下标为index的物品
select[index] = true;
knapsack(target - weights[index], index + 1);
// 下标为index的物品不满足则尝试下一个
select[index] = false;
knapsack(target, index + 1);
}
public static void main(String[] args) {
int[] weights = { 11, 9, 7, 6, 5 };
int target = 20;
Knapsack knapsack = new Knapsack(weights);
knapsack.knapsack(target, 0);
}
}