最大子数组和
Problem: 53. 最大子数组和
思路
双指针 但是用count保存双端的值 哪端count小哪端移动
解题方法
描述你的解题方法
复杂度
时间复杂度:
添加时间复杂度, 示例: $O(n)$
空间复杂度:
添加空间复杂度, 示例: $O(n)$
Code
// 这版性能一般
func maxSubArray(nums []int) int {
resultArray := nums[:]
leftIndex, rightIndex := 0, len(nums)-1
// leftStart, rightStart := leftIndex, rightIndex
leftCount, rightCount := nums[leftIndex], nums[rightIndex]
for {
// 当数组足够小直接退出,不用分
if len(nums) == 1 {
return nums[0]
}
// 判断下标距离, 如果下标相邻直接退出
if leftIndex+1 == rightIndex {
break
}
// 移动小的那端
if leftCount < rightCount {
leftIndex++
if leftCount < 0 {
resultArray = resultArray[leftIndex:]
// 数组变化时leftIndex要缩小,leftIndex归为0
rightIndex -= leftIndex
leftIndex = 0
leftCount = resultArray[leftIndex]
} else {
leftCount += resultArray[leftIndex]
}
} else {
rightIndex--
if rightCount < 0 {
// 数组变化时rightIndex++
resultArray = resultArray[:rightIndex+1]
rightCount = resultArray[rightIndex]
} else {
rightCount += resultArray[rightIndex]
}
}
}
return max(leftCount+rightCount, max(leftCount, rightCount))
}
func max(a int, b int) int {
if a > b {
return a
}
return b
}
Code
// 将消耗比较大的切片去掉 性能已经不错了
func maxSubArray(nums []int) int {
// 当数组足够小直接退出,不用分
if len(nums) == 1 {
return nums[0]
}
leftIndex, rightIndex := 0, len(nums)-1
leftCount, rightCount := nums[leftIndex], nums[rightIndex]
for {
// 判断下标距离, 如果下标相邻直接退出
if leftIndex+1 == rightIndex {
break
}
// 移动小的那端
if leftCount < rightCount {
leftIndex++
if leftCount < 0 {
// 小于0舍弃掉并换成当前值
leftCount = nums[leftIndex]
} else {
leftCount += nums[leftIndex]
}
} else {
rightIndex--
if rightCount < 0 {
// 小于0舍弃掉并换成当前值
rightCount = nums[rightIndex]
} else {
rightCount += nums[rightIndex]
}
}
}
return max(leftCount+rightCount, max(leftCount, rightCount))
}
func max(a int, b int) int {
if a > b {
return a
}
return b
}
// 优秀的递归 这个思路如果存储起来可以做到查询?
package main
func main() {
temp := maxSubArray([]int{-2, 1, -3, 4, -1, 2, 1, -5, 4})
println(temp)
// for _, v := range temp {
// println(v)
// }
// for i := 0; i < len(temp); i++ {
// for j := 0; j < len(temp[i]); j++ {
// print(temp[i][j], " ")
// }
// println()
// }
}
// maxSubArray 接收一个整数切片nums,并返回其最大子数组和
func maxSubArray(nums []int) int {
// 调用get函数构建线段树并查询整个数组的最大子数组和
return get(nums, 0, len(nums)-1).mSum
}
// pushUp 用于合并两个子节点的状态,生成父节点的状态
func pushUp(l, r Status) Status {
// iSum 是当前区间的元素和
iSum := l.iSum + r.iSum
// lSum 是当前区间以左端点为起点的最大子数组和
lSum := max(l.lSum, l.iSum+r.lSum)
// rSum 是当前区间以右端点为起点的最大子数组和
rSum := max(r.rSum, r.iSum+l.rSum)
// mSum 是当前区间的最大子数组和
mSum := max(max(l.mSum, r.mSum), l.rSum+r.lSum)
// 返回合并后的状态
return Status{lSum, rSum, mSum, iSum}
}
// get 用于递归地构建线段树并返回指定区间的状态
func get(nums []int, l, r int) Status {
// 如果区间只有一个元素,直接返回该元素的状态
if l == r {
return Status{nums[l], nums[l], nums[l], nums[l]}
}
// 计算中间位置
m := (l + r) >> 1
// 递归地构建左半部分线段树
lSub := get(nums, l, m)
// 递归地构建右半部分线段树
rSub := get(nums, m+1, r)
// 合并左右子树的状态,生成当前区间的状态
return pushUp(lSub, rSub)
}
// max 函数返回两个整数中的较大值
func max(x, y int) int {
if x > y {
return x
}
return y
}
// Status 结构体用于存储线段树节点的状态
type Status struct {
lSum, rSum, mSum, iSum int
}
// 字段解释:
// lSum: 当前区间以左端点为起点的最大子数组和
// rSum: 当前区间以右端点为起点的最大子数组和
// mSum: 当前区间的最大子数组和
// iSum: 当前区间的元素和
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通