最大子数组
暴力求解法 时间复杂度O(n^3)
暴力枚举,时间复杂度O(n3)
1、找出子数组的最左端点 for i<- 1 to n
2、找出子数组的最右端点 for j<- i to n
3、求和,找出最大值
sum = nums[i] +……+nums[j]; ans = max(ans, sum)
1 | public class Solution { |
时间复杂度O(n3) 求和操作被执行了很多次,有很多是重复计算的。
优化枚举 时间复杂度O(n^2)
算是半个暴力吧
原理:左端点相同的子数组,随着长度的增加,排在前面的元素被不断重复相加。如果我们记录下之前的求和结果,
就不需要对前面的元素再进行计算,比上面的少了一重循环。
1 | public static int maxSubArray(int[] nums) |
动态规划 时间复杂度O(n)
【只有子数组“前半部分”的和为正数时,子数组的求和才有可能最大】,在这个trick条件下,只需要遍历一次数组就可以。算法是:当从头开始遍历的元素的求和为正数时,继续向后遍历。当求和为负数时,重新开始计算求和,子数组的开始重置为下一个元素。
即对于任意一个子数组和,如果大于0,那么它再添加一个数,他的贡献是正值,如果子数组和小于0,再添加一个数,它的贡献则为负值,这时候不如将当前子数组舍掉,新数成为一个新数组。
1 | package a; |
其实虽然原题中指出数组里有正数和负数,经过实践和思考,这个算法同样适用于全是正数,或者全是负数的情况。当全为正数时,最大的和自然就是所有元素的和,当全为负数时,最大和自然就是其中最大的那个负数的值。通过此算法都能得到相应的结果。
最小子数组
1 | public class Solution { |
可参考
https://blog.csdn.net/wwe4023/article/details/72953559
http://www.cnblogs.com/theskulls/p/4886531.html