常见动态规划的解题思路及Java实现

项目介绍

  • 本项目通过分解各大厂的常见笔面试题,追本溯源至数据结构和算法的底层实现原理,知其然知其所以然;
  • 建立知识结构体系,方便查找,欢迎更多志同道合的朋友加入项目AlgorithmPractice,(欢迎提issue和pull request)。

Part One : 牛刀小试

这部分内容选取了几道比较简单的动态规划题目,来逐步了解什么是动态规划。

Part Two : 抛砖引玉

这部分内容只给出了基础的解,如果有更优化的解法,请在下方留言。

Part Three : 综合集锦

这部分内容的解法不限于动态规划,包括贪心、回溯等。

正文开始

1、青蛙跳台阶

  • 题目描述:在爬楼梯时,每次可向上走1阶台阶或2阶台阶,问有n阶楼 梯有多少种上楼的方式
  • 代码实现:ClimbStairs,测试用例:ClimbStairsTest
  • 设计思路:
    • 状态转换方程:
statusNum[i] = statusNum[i-1] + statusNum[i-2];
  • 注意事项:
    • 对于经常访问的数据,可以设置缓存,方便读取。
2、最大子段和

  • 题目描述:给定一个数组,求这个数组的连续子数组中,最大的那一段的和
  • 代码实现:LSS,测试用例:LSSTest
  • 设计思路:
  • 动态规划法:
状态转换方程:
LargestSum[i] = Math.max(LargestSum[i-1] + Sequence[i], Sequence[i]);
  • 动态规划优化法:
for(int i = 1; i < Sequence.length; i++){
	sum_temp += Sequence[i];
	if(sum_temp <= Sequence[i]){  //新开始
		sum_temp = Sequence[i];   //sum清空
		begin_temp = i;           //假定的起始位置
	}
	if(sum < sum_temp){
		sum = sum_temp;           //记录最大值
		begin = begin_temp;       //假定的起始地址赋值给起始地址
		end = i;                  //结束地址包括 i
	}
}
  • 分治法:
int leftValue = divide(Sequence, left, mid);
int rightValue = divide(Sequence, mid + 1, right);
int midValue = mid(Sequence, left, right);
  • 注意事项:
3、最长公共子序列

  • 题目描述:找出两个字符串最大匹配子串
  • 代码实现:LCS,测试用例:LCSTest
  • 设计思路:
    • 状态转换方程:
num_matrix[row][column] = num_matrix[row-1][column-1]+1;
num_matrix[row][column] = num_matrix[row-1][column];
num_matrix[row][column] = num_matrix[row][column-1];
  • 注意事项:
4、回文应用(Palindrome)
4.1、判断字符串是否属于回文

  • 题目描述:判断给定字符串是否是回文,默认单个字符不够成回文
  • 代码实现:
public boolean PalindromeJudge(String testString) {
	if(testString == null || testString.length() == 0){
		return false;
	}
	boolean flag = new StringBuffer(testString).reverse().toString().equals(testString);
	return flag;
}
  • 设计思路:字符串反转并匹配
  • 注意事项:
4.2、添加一个字符构造回文

  • 题目描述:给定一个字符串s,你可以从中添加一个字符,使得剩下的串是一个回文串,如果通过添加一个字符得到回文,则返回添加元素的位置(起始地址:1),否则返回 -1,如果本身是回文,返回中间的位置
  • 代码实现:CreatePalindromebyAdd,测试用例:CreatePalindromebyAddTest
  • 设计思路:
  • 注意事项:
4.3、删除一些字符构造回文

  • 题目描述:给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?输出需要删除的字符个数
  • 代码实现:CreatePalindromebyDelete,测试用例:CreatePalindromebyDeleteTest
  • 设计思路:字符串反转,并通过LCS算法计算最大相似数,那么不相似的那些数就需要删除了。
  • 注意事项:
4.4、查找给定字符串中最长的连续回文子串

  • 题目描述:
  • 代码实现:FindPalindrome,测试用例:FindPalindromeTest
    • 4.4.1、暴力法
    • 4.4.2、中心扩散法
    • 4.4.3、Manacher 算法
  • 设计思路:
    • 4.4.1、暴力法
    • 4.4.2、中心扩散法
    • 4.4.3、Manacher 算法
  • 注意事项:
5、送货最短路径

  • 题目描述:
    某物流派送员p,需要给a、b、c、d,4个快递点派送包裹, 请问派送员需要选择什么的路线,才能完成最短路程的派送。假设如图派送员的起点坐标(0,0),派送路线只能沿着图中的方格边行驶,每个小格都是正方形,且边长为1,如p到d的距离就是4。随机输入n个派送点坐标,求输出最短派送路线值(从起点开始完成n个点派送并回到起始点的距离)。
    在这里插入图片描述
  • 代码实现:
  • 设计思路:
    • 贪心算法
    • 回溯法
  • 注意事项:
6、最佳调度问题

  • 题目描述:设有n个任务由k个可并行工作的机器来完成,完成任务i需要时间为taskspendTime。试设计一个算法找出完成这n个任务的最佳调度,使完成全部任务的时间最早
  • 代码实现:OptimalSchedule,测试用例:OptimalScheduleTest
  • 设计思路:
  • 注意事项:
7、最长递增子序列

  • 题目描述:在一个给定的数值序列中,找到一个子序列,使得这个子序列元素的数值依次递增,并且这个子序列的长度尽可能地大。最长递增子序列中的元素在原序列中不一定是连续的
  • 代码实现:LIS,测试用例:LISTest
  • 设计思路:
  • 注意事项:
8、最大正方形

9、编辑距离

  • 题目描述:
    编辑距离指的是在两个单词之间,由其中一个单词转换为另一个单词所需要的最少单字符编辑操作次数。在这里定义的单字符编辑操作有且仅有三种:插入(Insertion)、删除(Deletion)、替换(Substitution)
    譬如,“kitten” 和 “sitting” 这两个单词,由 “kitten” 转换为 “sitting” 需要的最少单字符编辑操作有:
    1.kitten → sitten (substitution of “s” for “k”)
    2.sitten → sittin (substitution of “i” for “e”)
    3.sittin → sitting (insertion of “g” at the end)
    因此,“kitten” 和 “sitting” 这两个单词之间的编辑距离为 3 。
  • 代码实现:EditDistance,测试用例:EditDistanceTest
  • 设计思路:
    • 状态转换方程:
if (c1[i-1] == c2[j-1]) {
  comp[i][j] = comp[i - 1][j - 1];
} else {
  comp[i][j] = Math.min(Math.min(comp[i - 1][j - 1], comp[i][j - 1]), comp[i - 1][j]) + 1;
}
  • 注意事项:
a、背包问题(backpack)

  • 题目描述:
  • 代码实现:backpack,测试用例:
  • 设计思路:
  • 注意事项:
b、合唱团(Choir)

  • 题目描述:有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n个学生中按照顺序选取 ChoseNum名学生,要求相邻两个学生的位置编号的差不超过 d,使得这 ChoseNum个学生的能力值的乘积最大,你能返回最大的乘积吗?
  • 代码实现:
  • 设计思路:
    • 动态规划:
    • 回溯法:
  • 注意事项:
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值