递归的四条基本准则
-
基准情形
必须总要有某些基准情形,它无需递归就能解出
-
不断推进
对于那些需要递归求解的情形,每一次递归调用都必须使状况朝向一种基准情形推进
-
设计法则
假设所有的递归调用都能运行
-
合成效益法则
在求解一个问题的同一实例时,切勿在不同的递归调用中做重复性的工作。
例:求整数的二进制中 1 的 个数
public class T1 {
public static int num(int N)
{
// 基准情形
if (N < 2)
{
return N;
}
// 如果 是偶数 则,不 + 1。 奇数则 + 1
return N % 2 + num(N / 2);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(num(3));
}
}
例: 编写带有下列声明的例程
public void permute(String str);
public void permute(char [] str, int low, int high);
第一个例程是个驱动程序,它调用第二个例程并显示 String str 中的字符的所有排列。如果 str 是"abc",那么输出的就是 abc, acb, bac, bca, cab, cba。第二个例程使用递归。
/**
* @author 小喵钓鱼
* @date 2020-02-13 12:58
* @veision 1.10
*/
public class T2_fulfill {
public void permute(String str){
// 将 String 类型转变为 char 数组
char[] list = str.toCharArray();
permute(list, 0, list.length - 1);
}
/**
*
* @param str 字符数组
* @param low 最低位
* @param high 最高位
* 递归思路 如果 low == high 则为基本准形,输出。否则进行 位置变换,继续递归
* 1. 第一层循环的是第一位的字符
* 2. 第二层分别对应循环的是 第二位的字符(第一位已固定)
* ..... 依此类推。到最后一层,就不断进行输出了。。
*/
private void permute(char [] str, int low, int high){
int i; // 循环小能手,辅助
if (low == high)
{
// 最底下一层递归时,递归头
StringBuilder cout = new StringBuilder(); // 创建 builder 类型来构建输出字符串
for (int j = 0; j <= high; j++)
cout.append(str[j]);
// 输出 + 换行
System.out.println(cout);
}
else {
for (i = low; i <= high; i++)
{
// 1. 交换位置
char temp = str[i];
str[i] = str[low];
str[low] = temp;
// 2. 进入下一级
permute(str, low + 1, high);
// 复原位置
temp = str[i];
str[i] = str[low];
str[low] = temp;
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
T2_fulfill t2_fulfill = new T2_fulfill();
t2_fulfill.permute("abcd");
}
}