描述
给你一个n,,和一个长度为n的数组,在不同时选位置相邻的两个数的基础上,求该序列的最大子序列和(挑选出的子序列可以为空)。
方法一
思路
- 枚举,递归,回溯;
- 所求子序列集合要求各个元素之间互不相邻,假设所给数组为arr,对于下标为index的元素总共两种选择,将其放入子序列集合或者是不放入,那么便存在如下递推公式:
f(n-1)表示不要当前元素,f(n-2)表示将当前元素纳入最大子序列集合中,n需要大于等于3,
而当n = 1时,
当n = 2时, - 故可以依据上述递推公式,递归计算不相邻最大子序列和。
- 代码如下:
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 计算
* @param n int整型 数组的长度
* @param array int整型一维数组 长度为n的数组
* @return long长整型
*/
public long subsequence (int n, int[] array) {
return getMax(0,array);
}
private long getMax(int start,int[] array){
if (start >= array.length){
return 0;
}
// 子序列中包含array[start]的最大子序列和
long taken = 0;
// 子序列中不包含array[start]的最大子序列和
long untaken = 0;
// 不包含
untaken = getMax(start + 1,array);
// 若array[start] 小于等于0,则直接不要该数
if (array[start] <= 0){
return untaken;
}
// 包含
taken = getMax(start + 2,array) + array[start];
// 取最大值
return Math.max(taken,untaken);
}
}- 时间复杂度:
,递归函数的计算时间复杂度为指数级;
- 空间复杂度:
,递归调用栈的空间大小为n。
方法二
思路
- 动态规划;
- 方法一的时间复杂度过大,程序运行期间栈溢出;
- 方法一在递归运算中会有很多的冗余计算,譬如说在计算f(4)时,需要取计算f(3),f(2),f(1)等。
- 故可以在采用自底向上的方法,依据方法一的递推公式,记录每一个子问题的最大子序列和,从而降低时间复杂度。
- 创建一维数组dp存放计算的结果
- 依次计算f(1),f(2),f(3)……f(n)
- f(n)即为所求的不相邻最大子序列和。
- 对于数组[4,3,2,1,5,6,7]参考下图示例:
- 代码如下:
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 计算
* @param n int整型 数组的长度
* @param array int整型一维数组 长度为n的数组
* @return long长整型
*/
public long subsequence (int n, int[] array) {
if (n == 0){
return 0;
}
// 创建一维数组,辅助计算
long[] dp = new long[n];
// 当序列长度为1时
dp[0] = Math.max(0,array[0]);
if (n == 1){
return dp[0];
}
// 序列长度为2时
dp[1] = Math.max(dp[1],array[1]);
// 遍历
for(int i = 2;i < n;++i){
dp[i] = Math.max(dp[i-1],dp[i-2] + array[i]);
}
return dp[n-1];
}
}- 时间复杂度:
,一层循环;
- 空间复杂度:
,一维数组;
方法三
思路
- 动态规划
- 方法二的空间复杂度为
,可以考虑将其降低为
;
- 在计算f(n)中实际上用到的也就是f(n-1)和f(n-2),所以只需设置两个变量b(f(n-1)),a(f(n-2)),
在每一轮计算过后更新a=b,b=f(n)即可。
- 代码如下:
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 计算
* @param n int整型 数组的长度
* @param array int整型一维数组 长度为n的数组
* @return long长整型
*/
public long subsequence (int n, int[] array) {
if (n == 0){
return 0;
}
// 当序列长度为1时
long a = Math.max(0,array[0]);
if (n == 1){
return a;
}
// 序列长度为2时
long b = Math.max(a,array[1]);
// 遍历
for(int i = 2;i < n;++i){
long temp = b;
b = Math.max(b,a + array[i]);
a = temp;
}
return b;
}
}- 时间复杂度:
,一重循环;
- 空间复杂度:
,常数级空间复杂度。

京公网安备 11010502036488号