递归
程序调用自身的
编程技巧
称为递归
public static void show() {
show();
}
它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量
一般来说,递归需要有
边界条件
、
递归前进段
(函数进栈过程)和
递归返回段
(函数弹栈过程)。当边界条件不满足时,递归前进;当边界条件满足时,递归返回
分治算法
分治算法就是将
原问题划分成
n
个规模较小,并且结构与原问题相似的子问题
,递归地解决这些子问
题,然后再合并其结果,就得到原问题的解
分治算法的递归实现中,每一层递归都会涉及这样三个操作:
- 分解:将原问题分解成一系列子问题
- 解决:递归地求解各个子问题,若子问题足够小,则直接求解
- 合并:将子问题的结果合并成原问题
分治算法能解决的问题,一般都需要满足下面这几个条件:
- 原问题与分解成的小问题具有相同的模式
- 原问题分解成的子问题可以独立求解,子问题之间没有相关性
- 具有分解终止条件,也就是说,当问题足够小,可以直接求解
-
可以将子问题合并成原问题,而这个合并操作的复杂度不能太高,否则就起不到减小算法总体复杂度的效果了
【另外说明】
- 但凡能用数学归纳法解决的问题,都可以使用分治思想
- 分治思想不一定使用递归结构
一、大整数乘法问题
1.
问题
求两个较大的数相乘
2.
求解思路
如果将大整数分成多段,则导致快速傅里叶变换的产生,能够在O(nlogn)内解决
3.代码实现
public class BigIntegerMultiplication {
public static void main(String[] args) {
long x = 12345678; long y = 12345678;
long product = multi(x, y, 4);
System.out.println(product);
}
private static long multi(long x, long y, int n) {
// n 表示深度
if (x == 0 || y == 0) {
return 0;
}
if (n == 1) {
return x * y;
}
long A = (long) (x / Math.pow(10, n / 2));
long B = (long) (x - A * Math.pow(10, n / 2));
long C = (long) (y / Math.pow(10, n / 2));
long D = (long) (y - C * Math.pow(10, n / 2));
long E = multi(A, C, n / 2);
long F = multi(B, D, n / 2);
long G = multi(A + B, C + D, n / 2);
return (long) (E * Math.pow(10, n) + (G - E - F) * Math.pow(10, n / 2) + F);
}
}
二、全排列
1.
问题
求解字符串
“ABC”
中所有字符的全排列(不包含重复)
2.
求解思路
- 先确定第一位,再排列剩下的;
- 再确定第二位,再排列剩下的;
- 再确定第....位,直到没有剩下的位置。
- 然后回看上一位,看是否可以交换位置,找出不同的排列