我试图找到一张excel表中行数的连续数字的最小总和。 10.000行。
1 200
2 -100
3 -300
4 100
5 100
6 100
这应该给出-400和2行(当然这可以在另一个公式中)。
1 0
2 100
3 -100
4 -100
5 -100
6 100
7 -100
8 100
这应该给出-300和3行等。
谢谢!
答案 0 :(得分:2)
使用数组这个过程在10,000行上花费3-4秒:
Sub minarr()
Dim i&, j&
Dim rngArr() As Variant
Dim sum As Double
Dim frstrw As Long
Dim lstrw As Long
Dim lastrow As Long
Dim ws As Worksheet
Dim Minout As Double
Set ws = Sheets("Sheet28") 'Change to your sheet
'Change column A to the column of your numbers in the next two lines.
lastrow = ws.Range("A" & ws.Rows.Count).End(xlUp).row
rngArr = ws.Range("A1:A" & lastrow).Value
For i = 1 To lastrow
sum = rngArr(i, 1)
For j = i + 1 To lastrow
sum = sum + rngArr(j, 1)
If sum < Minout Then
Minout = sum
frstrw = i
lstrw = j
End If
Next j
Next i
Debug.Print Minout
Debug.Print frstrw
Debug.Print lstrw
End Sub
答案 1 :(得分:2)
Here is a debugged O(n)
solution. It is virtually instantaneous with 10,000 items. The algorithm is a variation of Kadane's algorithm for solving the maximum subarray problem (which @rajah9 points out as being a close match to this problem):
Function MinSum(Target As Range) As Variant
'Target is a 1-dimensional range of numbers
'Returns a variant array containing
'0) The minimum sum of consecutive numbers in R
'1) The starting index of the sum
'2) The ending index of the sum
Dim i As Long, n As Long
Dim A As Variant 'A(i,1) = value of best subsequence ending at i, A(i,2) is corresponding start value
Dim v As Variant 'currently scanned value
Dim minS As Variant 'the min sum
Dim minAt As Variant 'where it occurs in A
With Target
'initialize
n = .Cells.Count
ReDim A(1 To n, 1 To 2)
v = .Cells(1)
minS = v
minAt = 1
A(1, 1) = v
A(1, 2) = 1
'main loop
For i = 2 To n
v = .Cells(i)
'the best sequence ending at i extends previous one if previous one is negative:
If A(i - 1, 1) < 0 Then
A(i, 1) = A(i - 1, 1) + v
A(i, 2) = A(i - 1, 2) 'extend current subsequence
Else 'start new subsequence
A(i, 1) = v
A(i, 2) = i
End If
'see if we have a new min:
If A(i, 1) < minS Then
minS = A(i, 1)
minAt = i
End If
Next i
End With
MinSum = Array(minS, A(minAt, 2), minAt)
End Function
It returns an array which gives both the minimal sum and two indices, start and end of the sum in the array. It can be used as an array formula:
In the above screenshot, I have =RANDBETWEEN(-100,100)
in cells A1:A10000 and then in cells C1:E1 I have {=MinSum(A1:A10000)}
(Ctrl+Shift+Enter to accept as an array formula). Both the computation of the 10,000 random numbers and the determination of the minsum takes less than half a second.