一、分治法(Divide and Conquer)
定义
分治法是一种将大问题分解成若干个小问题,递归地解决这些小问题,然后将这些小问题的解合并起来得到原问题的解的算法策略。(子问题之间相互独立)
基本步骤
1.分解:将原问题分解为若干个规模较小、相互独立、与原问题形式相同的子问题。
2.解决:递归地解决这些子问题。如果子问题的规模足够小,则直接求解。
3.合并:将子问题的解合并成原问题的解
示例
归并排序就是一种典型的分治算法。归并排序将一个数组分成两半,分别对这两半进行排序,之后将排序好的两半合并成一个有序的数组。
二、动态规划法(Dynamic Programming, DP)
定义
动态规划法是通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。与分治法不同的是,动态规划解决的子问题往往不是互相独立的,即不同的子问题之间可能共享一些子子问题的解。动态规划通过存储这些子问题的解来避免重复计算,从而提高效率。
基本步骤
1.定义状态:将问题分解为若干重叠的子问题,并定义状态来表示这些子问题的解。
2.状态转移方程:找出状态之间的关系,即如何从已知状态推导出新的状态(状态转移方程)。
3.初始化:确定初始状态的值。
4.计算顺序:根据状态转移方程,按照一定的顺序计算所有状态的值。
5.答案:根据问题的需求,从计算出的状态中找出答案。
示例
斐波那契数列的求解就可以通过动态规划来解决。通过定义dp[i]为第i个斐波那契数,那么状态转移方程就是dp[i] = dp[i-1] + dp[i-2],初始条件是dp[0] = 0和dp[1] = 1
public class FibonacciDP {
// 使用动态规划计算斐波那契数列的第n项
public static int fibonacci(int n) {
// 基本情况
if (n <= 1) {
return n;
}
// 创建一个数组来保存中间结果
int[] dp = new int[n + 1];
// 初始化前两个值
dp[0] = 0;
dp[1] = 1;
// 使用动态规划填充数组
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
// 返回结果
return dp[n];
}
public static void main(String[] args) {
int n = 10; // 假设我们要计算斐波那契数列的第10项
System.out.println("Fibonacci number at position " + n + " is " + fibonacci(n));
}
}