1 实现和特性
1.1 分治(递归的一种)
先拆分为子问题,最后子结果合并
例如:
代码模板
1.2 回溯(Backtracking)
采用试错的思想,尝试分步地去解决一个问题
在分步解决问题的过程中,发现现有分步结果无效时,将取消上一步甚至几步的计算
再通过其他可能的分步方式再次尝试解决
结果:
- 找到一个可能存在正确答案
- 尝试了所有可能分步后,没有答案
最坏时间复杂度为指数级
典型问题: 八皇后,数独、背包
2 算法题解
1)[50] Pow(x, n)
计算xn
210 == (25)2 --> ((22)*2)2
要注意奇偶性
pow(x, n)
subproblem: subresult = pow(x, n/2)
merge:
if n % 2 == 1 {
result = subresult * subresult * x;奇数的时候
} else {
result = subresult * subresult; 偶数的时候
考虑幂为 正、负 、0的三种情况
/*
* @lc app=leetcode.cn id=50 lang=java
*
* [50] Pow(x, n)
* 分治
*
*/
// @lc code=start
class Solution {
private double fastPow(double x, long n) {
if (n == 0) {
return 1.0;
}
double half = fastPow(x, n/2);
if (n % 2 == 0) return half * half; // 当n为偶数
else return half * half * x; // n 为奇数(2^5)=(2^2)^2 * 2
}
public double myPow(double x, int n) {
long N = n;
// 当幂为负数时,x要变为 1/x, 再把n变为正数计算 (1/x)^-n^
if (N < 0) {
x = 1 / x;
N = -N;
}
return fastPow(x, N);
}
}
// @lc code=end
2)[78] 子集
分治:
通过向下递归,每一层就代表给出的数组的第几个元素
- 第一层 无1 与有1
- 第二层 无2,与有2
import java.util.ArrayList;
import java.util.List;
/*
* @lc app=leetcode.cn id=78 lang=java
*
* [78] 子集
*
*/
// @lc code=start
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
// 给的数组为空就直接返回空,不为空就向下
if (nums != null) backtrack(res, nums, new ArrayList<Integer>(), 0);
return res;
}
public void backtrack(List<List<Integer>> res, int[] nums, List<Integer> list, int index) {
// 终止条件:递归层数等于输入数组长度时,代表递归已经到最后一层了,将所有子树的结果合并
if (index == nums.length) {
res.add(new ArrayList<Integer>(list));
return;
}
// 两条分支,第一条不加元素
backtrack(res, nums, list, index + 1);
list.add(nums[index]);
// 第二条要加元素
backtrack(res, nums, list, index + 1);
// 因为改变的是参数,参数是向下传递的,所以为了不影响上层,最后需要将这层list添加的删除
list.remove(list.size() - 1);
}
}
// @lc code=end
2)[51] N皇后
#
# @lc app=leetcode.cn id=51 lang=python3
#
# [51] N皇后
#
# @lc code=start
class Solution:
# 递归的入口
def solveNQueens(self, n: int) -> List[List[str]]:
if n < 1: return []
self.result = []
self.cols = set()
self.pie = set()
self.na = set()
self.DFS(n, 0, [])
return self.generate_result(n)
def DFS(self, n, row, cur_state):
# 终止条件:当row到棋盘的最后一层时,所有皇后排列完毕,将所有结果加到结果中
if row >= n:
self.result.append(cur_state)
return
# 依次判断当前层每个对角线是否满足皇后唯一
for col in range(n):
if col in self.cols or row + col in self.pie or row - col in self.na:
continue
# 将皇后放在当前位置,并记录对角线常数
self.cols.add(col)
self.pie.add(row + col)
self.na.add(row - col)
# 进入下层递归
self.DFS(n, row + 1, cur_state + [col])
# 清除递归当前层添加的内容,防止影响上层
self.cols.remove(col)
self.pie.remove(row + col)
self.na.remove(row - col)
# 棋盘的输出
def generate_result(self, n):
board = []
for res in self.result:
for i in res:
board.append("." * i + "Q" + "." * (n - i - 1))
return [board[i: i + n] for i in range(0, len(board), n)]
# @lc code=end