介绍分治、动态规划、回溯分别是什么?有什么联系和区别?给出对象的场景和java代码?
一、分治算法(Divide and Conquer)
概念:
分治算法是将一个复杂问题分成若干个子问题,每个子问题结构与原问题类似,然后递归地解决这些子问题,最后将子问题的结果合并得到原问题的解。
特点:
- 将大问题递归分解成小问题。
- 子问题之间通常 相互独立。
- 最终通过合并操作构造原问题的解。
典型场景:
- 快速排序(Quick Sort)
- 归并排序(Merge Sort)
- 最大子数组和(Divide and Conquer 解法)
Java 示例(归并排序):
public class MergeSort {public static void mergeSort(int[] arr, int left, int right) {if (left >= right) return;int mid = (left + right) / 2;mergeSort(arr, left, mid);mergeSort(arr, mid + 1, right);merge(arr, left, mid, right);}private static void merge(int[] arr, int left, int mid, int right) {int[] temp = new int[right - left + 1];int i = left, j = mid + 1, k = 0;while (i <= mid && j <= right) {temp[k++] = arr[i] <= arr[j] ? arr[i++] : arr[j++];}while (i <= mid) temp[k++] = arr[i++];while (j <= right) temp[k++] = arr[j++];for (int m = 0; m < temp.length; m++) {arr[left + m] = temp[m];}}
}
二、动态规划(Dynamic Programming)
概念:
动态规划通过将问题分解为子问题,记录已解决的子问题的解(通常用数组或表格存储),避免重复计算,从而提高效率。
特点:
- 子问题之间存在 重叠子问题(Overlapping Subproblems)。
- 存在 最优子结构(Optimal Substructure)。
- 使用 记忆化搜索 或 自底向上表格法。
典型场景:
- 斐波那契数列
- 背包问题
- 最长公共子序列(LCS)
Java 示例(斐波那契数列):
public class FibonacciDP {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];}
}
三、回溯算法(Backtracking)
概念:
回溯是一种试探性方法,逐步构造问题的解,如果发现当前步骤不能得到正确解,就 回退(Backtrack) 到上一步重新尝试。
特点:
- 适用于组合、排列、子集等枚举类问题。
- 类似深度优先搜索(DFS),关键在于剪枝(优化性能)。
典型场景:
- 八皇后问题
- 子集生成、全排列
- 数独求解
Java 示例(全排列):
import java.util.*;public class Permutations {public static List<List<Integer>> permute(int[] nums) {List<List<Integer>> result = new ArrayList<>();backtrack(nums, new boolean[nums.length], new ArrayList<>(), result);return result;}private static void backtrack(int[] nums, boolean[] used, List<Integer> temp, List<List<Integer>> result) {if (temp.size() == nums.length) {result.add(new ArrayList<>(temp));return;}for (int i = 0; i < nums.length; i++) {if (used[i]) continue;used[i] = true;temp.add(nums[i]);backtrack(nums, used, temp, result);temp.remove(temp.size() - 1);used[i] = false;}}
}
四、三者的联系与区别
特性/算法 | 分治(Divide & Conquer) | 动态规划(DP) | 回溯(Backtracking) |
---|---|---|---|
子问题独立 | 是 | 否(有重叠子问题) | 否 |
解空间结构 | 树(递归分解) | 网格/图结构 | 树(搜索树) |
是否剪枝 | 否 | 是(通过缓存) | 是(通过条件剪枝) |
应用场景 | 排序、矩阵分割、最大子数组 | 最优化问题、序列问题 | 组合问题、数独、图遍历等 |
解法策略 | 递归 + 合并 | 递归 + 记忆/状态转移 | DFS + 回退 + 剪枝 |
总结:
- 分治适合问题可以被拆解为若干 独立 子问题的情形;
- 动态规划适合问题具有 重叠子问题和最优子结构;
- 回溯适合在解空间中试探性地寻找满足条件的所有解,适合 搜索类问题。