从递归到动态规划(一维)

从递归到一维动态规划的理解

动态规划是一种通过把原问题分解为相对简单的子问题,并保存子问题的解来避免重复计算,从而解决复杂问题的算法策略。一维动态规划是动态规划中较为基础的一类,它通常只需要一个一维数组来保存子问题的解。我们可以从递归的角度逐步引出一维动态规划。

递归的基本概念

递归是指在函数的定义中使用函数自身的方法。在解决问题时,递归通常将大问题分解为形式相同的小问题,直到达到最小的、可以直接求解的子问题(即递归的终止条件)。不过,递归可能会存在大量的重复计算,导致时间复杂度很高。

以斐波那契数列为例理解从递归到一维动态规划的转变步骤

1. 递归实现斐波那契数列

斐波那契数列的定义为:(F(n) = F(n - 1)+F(n - 2)),其中 (F(0)=0,(F(1)=1。

java 复制代码
public static int fib1(int n) {
		return f1(n);
	}

	public static int f1(int i) {
		if (i == 0) {
			return 0;
		}
		if (i == 1) {
			return 1;
		}
		return f1(i - 1) + f1(i - 2);
	}

递归的问题:在计算 F(n) 时,会多次重复计算 F(n - 1)、F(n - 2) 等子问题。例如,计算 F(5) 时,(F(3) 会被多次计算,这会导致时间复杂度呈指数级增长,为 O(2^n)。

2. 记忆化搜索实现斐波那契数列(自顶向下动态规划)

为了避免递归中的重复计算,我们可以使用一维数组来保存已经计算过的子问题的解,遇到时直接返回。

java 复制代码
public static int fib2(int n) {
		int[] dp = new int[n + 1];
		Arrays.fill(dp, -1);
		return f2(n, dp);
	}

	public static int f2(int i, int[] dp) {
		if (i == 0) {
			return 0;
		}
		if (i == 1) {
			return 1;
		}
		if (dp[i] != -1) {
			return dp[i];
		}
		int ans = f2(i - 1, dp) + f2(i - 2, dp);
		dp[i] = ans;
		return ans;
	}
3. 严格位置依赖实现斐波那契数列(自底向上动态规划)

是利用数列项间严格位置依赖关系,从最小子问题起按序计算,避免递归重复计算以提升效率,让代码更易读且有空间优化潜力。

java 复制代码
public static int fib3(int n) {
		if (n == 0) {
			return 0;
		}
		if (n == 1) {
			return 1;
		}
		int[] dp = new int[n + 1];
		dp[1] = 1;
		for (int i = 2; i <= n; i++) {
			dp[i] = dp[i - 1] + dp[i - 2];
		}
		return dp[n];
	}
4. 用有限几个变量优化空间

为了简化代码。

java 复制代码
public static int fib4(int n) {
		if (n == 0) {
			return 0;
		}
		if (n == 1) {
			return 1;
		}
		int lastLast = 0, last = 1;
		for (int i = 2, cur; i <= n; i++) {
			cur = lastLast + last;
			lastLast = last;
			last = cur;
		}
		return last;
	}

相应题目链接

509. 斐波那契数 - 力扣(LeetCode)

983. 最低票价 - 力扣(LeetCode)

91. 解码方法 - 力扣(LeetCode)

639. 解码方法 II - 力扣(LeetCode)

264. 丑数 II - 力扣(LeetCode)

32. 最长有效括号 - 力扣(LeetCode)

467. 环绕字符串中唯一的子字符串 - 力扣(LeetCode)

940. 不同的子序列 II - 力扣(LeetCode)

相关推荐
全糖可乐气泡水几秒前
Codex适配国产信创环境安装部署与技术适配全解析
开发语言·git·python·算法·百度
h_a_o777oah13 分钟前
状态机+划分型 DP :深度解析K-划分问题下 DP 状态的转移逻辑(洛谷P2679 P2331 附C++代码)
c++·算法·动态规划·acm·状态机dp·划分型dp·滚动数组优化
05候补工程师20 分钟前
从算法理想向工程现实的跨越:SLAM 核心架构、思维误区与 Nav2 实战避坑指南
人工智能·算法·安全·架构·机器人
手写码匠2 小时前
Android 17 适配实战指南:新特性解读、隐私变更与迁移全攻略
人工智能·深度学习·算法·aigc
珊瑚里的鱼2 小时前
leetcode42雨水
算法·leetcode
水木流年追梦2 小时前
大模型入门-大模型的推理策略
开发语言·python·算法·正则表达式·prompt
生成论实验室2 小时前
用事件关系网络重新理解AI(三):激活函数、微调与元学习
人工智能·学习·算法·语言模型·可信计算技术
Narv工程师2 小时前
嵌入式机器人控制器算力评估:从DMIPS到WCET的完整指南
人工智能·算法·机器学习
蒟蒻的贤2 小时前
实训1227
算法
liulilittle2 小时前
TCP UCP:基于卡尔曼滤波的BBR增强型拥塞控制算法
linux·网络·c++·tcp/ip·算法·c·通讯