题目描述
给你一个n(1≤n≤10^5),和一个长度为n的数组,在不同时选位置相邻的两个数的基础上,求该序列的最大子序列和(挑选出的子序列可以为空)。
方法一:动态规划
求解思路
对于本题目要求在不相邻的位置时求解最大子序列的和。这道题目是一个01背包问题,即根据前边计算好的i个节点的结果判断是否选择当前节点,我们假定dp[i]为i位置最大子序列的和,其状态转移方程为: ,其中array[i]表示题目所给的数组在第i位置上的数,根据以上描述即可求解出相应的结果。
解题代码
import java.util.*; public class Solution { public long subsequence (int n, int[] array) { if (n == 0) { return 0; } long[] hydp = new long[n]; // 创建一维数组,辅助计算 hydp[0] = Math.max(0,array[0]); // 当序列长度为1时 if (n == 1) { return hydp[0]; } // 序列长度为2 hydp[1] = Math.max(hydp[1],array[1]); // 对hydp进行遍历 for(int i = 2;i < n;++i) { hydp[i] = Math.max(hydp[i-1],hydp[i-2] + array[i]); } return hydp[n-1]; // 返回结果 } }
复杂度分析
时间复杂度:使用了一层循环,因此时间复杂度为
空间复杂度:引入dp[n]数组,因此空间复杂度为
方法二:优化方法--动态优化
求解思路
对于本题目的求解,我们参考斐波那契数列的通项公式,在计算第n个值时,发现其结果可以由前两位的结果得出,跟其他位置的值无联系。因此我们对于第一种方法做出优化。
解题代码
import java.util.*; public class Solution { public long subsequence (int n, int[] array) { long i=0,j=0,k=0; // 声明ijk三个变量 for(int x=n-1;x>=0;x--) { k=Math.max(i,array[x]+j); // k存储最大值 j=i; // 更新j值 i=k; // 更新i值 } return k; // 返回结果 } }
复杂度分析
时间复杂度:一层循环,因此时间复杂度为
空间复杂度:引入one,two两个变量,常数级内存空间,因此空间复杂度为