虽然我走得很慢,但我从不后退!
千里之行,始于足下
今天的练习开始:
3. 最大子序和
建议:使用动态规划和分治算法
3.1、题目描述
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4] 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大和为 6。
进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
3.2、解法
方式一:暴力破解
自己解法:
public class SubArraySum {
public static void main ( String[] args ) {
int[] arr = {-2,1,-3,4,-1,2,1,-5,4};
System.out.println ("最大值为:" + maxSum ( arr ) );
}
/**
* 暴力破解法
* 时间复杂度 O(N^2)
* @param arr
* @return
*/
public static int maxSum(int[] arr){
//1.创建一个集合
ArrayList<Integer> list = new ArrayList<> ();
//2.将数组元素从下标0开始往后加,每得到一个和就存入集合list中
for ( int i = 0 ; i < arr.length - 1 ; i++ ) {
int sum = arr[i];
for ( int j = i + 1 ; j < arr.length ; j++ ) {
sum = sum + arr[j];
list.add ( sum );
}
}
//3.将集合元素进行排序,输出最大的值就是和最大的
Object[] array = list.toArray ( );
Arrays.sort ( array );
return (Integer)array[array.length - 1];
}
}
复杂度分析
-
时间复杂度O(n^2)
-
空间复杂度O(n)
他人解法:
public class Solution {
public int maxSubArray(int[] nums) {
int len = nums.length;
int res = Integer.MIN_VALUE;
for (int i = 0; i < len; i++) {
int sum = 0;
for (int j = i; j < len; j++) {
sum += nums[j];
res = Math.max(res, sum);
}
}
return res;
}
}
复杂度分析
方式二、动态规划
思路:
官方解法:
public int maxSubArray(int[] nums) {
int pre = 0, maxAns = nums[0];
for (int x : nums) {
pre = Math.max(pre + x, x);
maxAns = Math.max(maxAns, pre);
}
return maxAns;
}
复杂度分析
-
时间复杂度:O(n),其中 n 为 nums 数组的长度。我们只需要遍历一遍数组即可求得答案。
-
空间复杂度:O(1)。我们只需要常数空间存放若干变量。