吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1798|回复: 1
收起左侧

[其他原创] [VBS][算法实战006]分治法解“最大子列和问题”

[复制链接]
老刘 发表于 2019-10-30 17:58
本帖最后由 老刘 于 2019-10-30 18:03 编辑

数学符号语言描述:
QQ截图20191030093051.jpg
文字描述:
最大子数列问题的目标是在数列的一维方向找到一个连续的子数列,使该子数列的和最大。例如,对一个数列 -2, 1, -3, 4, -1, 2, 1, -5, 4,其连续子数列中和最大的是 4, -1, 2, 1, 其和为6。
若最大子列和为负,则结果取0。

以下解法非最优(时间复杂度O(nlogn),已有O(n)的算法),仅为分治思想练习:

[Visual Basic] 纯文本查看 复制代码
Option Explicit
Dim Arr

Arr = Array(4,-3,5,-2,-1,2,6,-2) '为11
WScript.Echo Max(MaxSubseqSum(1,1,UBound(Arr) + 1),0)

Arr = Array(-2,1,-3,4,-1,2,1,-5,4) '为6
WScript.Echo Max(MaxSubseqSum(1,1,UBound(Arr) + 1),0)

Arr = Array(-2,11,-4,13,-5,-2) '为20
WScript.Echo Max(MaxSubseqSum(1,1,UBound(Arr) + 1),0)

Arr = Array(-2,6,-1,5,4,-7,2,3) '为14
WScript.Echo Max(MaxSubseqSum(1,1,UBound(Arr) + 1),0)

Function MaxSubseqSum(ByVal ptrListStart,ByVal ptrListMiddle,ByVal ptrListEnd)
        Dim numMaxLeft,numMaxRight,numMaxUnion
        
        Rem 求左半段最大子列和。
        If ptrListStart = ptrListMiddle Then '只有一个元素
                numMaxLeft = GetItem(Arr,ptrListStart)
        Else
                If (ptrListMiddle - ptrListStart + 1) Mod 2 = 0 Then '有偶数个元素,平均分配
                        numMaxLeft = MaxSubseqSum(ptrListStart,(ptrListStart + ptrListMiddle - 1)\2,ptrListMiddle)
                Else '有奇数个元素,左半段分配一个,右半段分配剩下的
                        numMaxLeft = MaxSubseqSum(ptrListStart,ptrListStart,ptrListMiddle)
                End If
        End If
        
        Rem 求右半段最大子列和。
        If ptrListEnd - ptrListMiddle = 1 Then '只有一个元素
                numMaxRight  = GetItem(Arr,ptrListEnd)
        Else
                If (ptrListEnd - ptrListMiddle) Mod 2 = 0 Then '偶数个元素
                        numMaxRight = MaxSubseqSum(ptrListMiddle + 1,(ptrListMiddle + ptrListEnd)\2,ptrListEnd)
                Else
                        numMaxRight = MaxSubseqSum(ptrListMiddle + 1,ptrListMiddle + 1,ptrListEnd)
                End If
        End If
        
        Rem 求左右合并最大子列和。
        Rem 左半边。
        Dim ptrNow,numUnionNow,numMaxUnionLeft,numMaxUnionRight
        numUnionNow = 0
        numMaxUnionLeft = 0
        For ptrNow = ptrListMiddle To ptrListStart Step -1
                numUnionNow = numUnionNow + GetItem(Arr,ptrNow)
                numMaxUnionLeft = Max(numMaxUnionLeft,numUnionNow)
        Next
        Rem 右半边。
        numUnionNow = 0
        numMaxUnionRight = 0
        For ptrNow = ptrListMiddle + 1 To ptrListEnd
                numUnionNow = numUnionNow + GetItem(Arr,ptrNow)
                numMaxUnionRight = Max(numMaxUnionRight,numUnionNow)
        Next
        Rem 求合并。
        numMaxUnion = numMaxUnionLeft + numMaxUnionRight
        
        Rem 左半段、右半段、左右合并取最大。
        MaxSubseqSum = Max(Max(numMaxLeft,numMaxRight),numMaxUnion)
End Function

Function GetItem(ByVal Arr,ByVal Ptr) '手动构造从1开始的数组
        GetItem = Arr(Ptr - 1)
End Function

Function Max(ByVal Num1,ByVal Num2)
        If Num1 > Num2 Then
                Max = Num1
        Else
                Max = Num2
        End If
End Function

免费评分

参与人数 2吾爱币 +6 热心值 +1 收起 理由
pumishuo + 1 我很赞同!
苏紫方璇 + 5 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

pumishuo 发表于 2019-11-12 00:18
vbs可以的
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-16 17:52

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表