不相邻最大子序列和
题目描述
给你一个 n ,和一个长度为 n 的数组,在不同时选位置相邻的两个数的基础上,求该序列的最大子序列和(挑选出的子序列可以为空)。
示例
- 示例1
输入返回值1
3,[1,2,3]
说明1
4
1
有 [], [1], [2], [3], [1,3] 4 种选取方式其中 [1,3] 选取最优,答案为 4 。
- 示例2
输入返回值1
4,[4,2,3,5]
说明1
9
1
其中 [4,5] 的选取方案是在满足不同时选取相邻位置的数的情况下是最优的答案。
解决方案
动态规划
根据题目的描述可以很快明白这是一个 01 背包问题,根据前边已经计算好的前 i 个节点的结果判断是否选择当前节点。
状态转移方程:
1 | dp[i] = Math.max(dp[i-1], dp[i-2]+arr[i-1]) |
边界条件:
1 | for (int i = 2; i <= n; i++) {} |
那么就可以根据这些判断出来的条件撸代码了。
1 | public long subsequence (int n, int[] array) { |
这样根据动态规划的理念,这个问题也就解决了。
动态规划优化
如果你还记得斐波那契数列优化版本的话,你就会发现这其中似乎有一些类似的地方,比如:计算当前第 i 个值的结果,只需要参考前两位的结果值,跟其他的都没有关系。
按照这个思路,重新理清楚思路,那么代码就来了!
1 | public long subsequence (int n, int[] array) { |
这个版本的优化主要在于空间复杂度的优化,以往需要一整个数组来记录,而现在只需要两个变量来代替,极大的节省了空间复杂度。
总结
算法只有你事必躬亲才会慢慢有成效,如果只靠一时的 100% check
,那么你是不会理解算法的精髓和含义。
个人备注
此博客内容均为作者学习所做笔记,侵删!
若转作其他用途,请注明来源!