问题描述:
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
进阶:
如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
问题分析:
其实这道题是典型的动态规划问题,也可以使用循环来解决这个问题,但是效率会很低下,但是数组的内容会对你的算法有很大的影响,比如
全为 负数,再比如,只有一个数据,这些都是特殊情况
在这里留下了几种方法,可以参考
--解决不了数组全为负数的情况
1,三重循环的暴力求解
2,双重循环的暴力求解
3,时间复杂度为o(n)的普通解法
4,时间复杂度为o(n)的动态规划
--可以解决数组全为负数的情况
5, 适应多种情况数组的动态规划解法
代码展示(已验证):
public class maxSubArray
{
/**
* @param args
*/
public static void main(String[] args)
{
int[] nums = {-2,1,-3,4,-1,2,1,-5,4};
//开始位置的选择 两个数加在一起 大于0
//结束位置的选择,几个数字加在一起大于零或者 前面是大数加了之后变小了不要
//如果全小于0,可以找出数组中最大的输出
// 没能解决数组全为负的问题
System.out.println("暴力求解 "+maxsubarray1(nums));
System.out.println("暴力求解升级版 "+maxsubarray2(nums));
System.out.println("o(n)的优化算法 "+maxsubarray3(nums));
System.out.println("o(n)的动态规划算法 "+maxsubarray4(nums));
//可解决数组全为负的情况
System.out.println("o(n)的动态规划算法,可解决数组全为负的情况 "+maxsubarray5(nums));
}
1,三重暴力求解 列出所有情况
// 1,暴力求解 列出所有情况
public static int maxsubarray1(int[] nums) {
int maxsum=0;
for(int i=0; i<nums.length-1; i++){
for(int j=i; j<nums.length; j++) {
int tempsum=0;
for(int k=i; k<=j; k++)
tempsum += nums[k];
if(tempsum > maxsum)
maxsum = tempsum;
}
}
return maxsum;
}
2, o(n^2)的暴力求解改进算法
//2, o(n^2)的暴力求解改进算法
public static int maxsubarray2(int[] nums) {
int maxsum = 0;
for(int i=0; i<nums.length; i++) {
int tempsum =0;
for(int j=i; j<nums.length; j++) {
tempsum += nums[j];
if(tempsum > maxsum)
maxsum = tempsum;
}
}
return maxsum;
}
3,o(n)的普通优化算法
//3,o(n)的优化算法(解决不了数组全为负的问题)
public static int maxsubarray3(int[] nums) {
int maxsum=0,tempsum=0;
for(int i=0; i<nums.length; i++) {
tempsum+=nums[i];
if(tempsum > maxsum)
maxsum = tempsum;
else if(tempsum < 0)
tempsum =0;
}
return maxsum;
}
4, o(n)的动态规划算法
//4, o(n)的动态规划算法
/*
* 求解思路:用sum(j) 表示 a1 到 aj 的和,很容易求出动态规划的递归表达式
* sum(j) = max(sum(j-1)+aj,aj)
* 可以清楚的返回最佳连续子序列和的起始位置和终点位置
*/
public static int maxsubarray4(int[] nums) {
int maxsum=0,tempsum=0,begin=0;
for(int i=0; i<nums.length; i++) {
if(tempsum > 0)
tempsum += nums[i];
else {
tempsum = nums[i];
begin = i;
}
if(tempsum > maxsum)
maxsum = tempsum;
//可以在这里获取最佳连续子序列的起点位置 begin 和 终点位置 i
}
return maxsum;
}
5,动态规划,可解决数组全为负的情况
//5,动态规划,可解决数组全为负的情况
public static int maxsubarray5(int[] nums) {
if(nums.length < 1) return 0;
if(nums.length == 1) return nums[0];
int[] dp = new int[nums.length];
dp[0] = nums[0];
int result = dp[0];
for(int i=1; i<nums.length; i++){
dp[i] = Math.max(dp[i-1]+nums[i],nums[i]);
result = Math.max(result,dp[i]);
}
return result;
}
}
泡泡:
动态规划的思想很重要,学起来也更难,但是冰冻三尺非一日之寒,还是要多多努力