给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
进阶:
如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
解不出来法一:
空间复杂度:$O(1)$
时间复杂度:$O(n3)$
//暴力解决问题,但是并不能解决,会超时
//引以为戒
func maxSubArray(nums []int) int {
if len(nums) == 0 {
return 0
}
if len(nums) == 1 {
return nums[0]
}
max := -0xffffffff
for i := 0; i < len(nums); i++ {
for j := i; j < len(nums); j++ {
temp := 0
for k := i; k <= j; k++ {
temp += nums[k]
}
if temp > max {
max = temp
}
}
}
return max
}
解法二:动态规划
空间复杂度:$O(1)$
时间复杂度:$O(n)$
//这里使用max记录最大值
//tmp记录当前值,如果当前值已经小于0,可以直接抛弃
//如果大于0,尝试更新max
func maxSubArray(nums []int) int {
max := int(^(int(^uint(0) >> 1)))
//fmt.Printf("(^uint(0) >> 1) = %d\n", (^uint(0) >> 1))
//fmt.Printf("int(^uint(0) >> 1) = %b\n", int(^uint(0) >> 1))
//fmt.Printf("int(^(int(^uint(0)))) = %b\n", int(^(int(^uint(0) >> 1))))
//fmt.Printf("int(^(int(^uint(0)))) = %b\n", (^(int(^uint(0) >> 1))))
//fmt.Printf("(^int(0) >> 1) = %b\n", (^int(0) >> 1))
//fmt.Printf("int(^int(0) >> 1) = %b\n", int(^int(0) >> 1))
//fmt.Printf("int(^(int(^int(0) >> 1))) = %b\n", int(^(int(^int(0) >> 1))))
tmp := 0
for _, v := range nums {
if tmp > 0 {
tmp += v
} else {
tmp = v
}
if max < tmp {
max = tmp
}
//fmt.Println(tmp)
}
return max
}
解法三:分治算法
空间复杂度:$O(1)$
时间复杂度:$O(nlogn)$
//分支算法的主要思路是将数组一份为二
//左边,中间一个,右边
//最大值肯定出现在左边,右边,穿过中间这三者之间
//关于这种算法的时间复杂度我没算太明白,但是有一个博文说的很清楚,把地址贴在算法的下方
func maxPart(nums []int, left int, right int) int {
if left == right {
return nums[left]
}
if left > right {
return int(^(int(^uint(0) >> 1)))
}
mid := (left + right) >> 1
maxLeft := maxPart(nums, left, mid - 1)
maxRight := maxPart(nums, mid + 1, right)
partLeftMax := 0
partRightMax := 0
sum := 0
for i := mid - 1; i >= left; i-- {
sum += nums[i]
if sum > partLeftMax {
partLeftMax = sum
}
}
sum = 0
for i := mid + 1; i <= right; i++ {
sum += nums[i]
if sum > partRightMax {
partRightMax = sum
}
}
partMidMax := partLeftMax + partRightMax + nums[mid]
tmp := 0
if maxLeft > maxRight {
tmp = maxLeft
} else {
tmp = maxRight
}
if tmp < partMidMax {
tmp = partMidMax
}
//fmt.Printf("left = %d right = %d tmp = %d\n", left, right, tmp)
return tmp
}
func maxSubArray(nums []int) int {
return maxPart(nums, 0, len(nums) - 1)
}
算法复杂度分析博文:https://www.cnblogs.com/genialx/p/10178182.html
在这里有一个问题还没解决,max初始值应该设定为一个int类型的最小值
int(^(int(^uint(0) >> 1)))为int最小值
但是为什么int(^(^uint(0) >> 1))就不可以