如何优化我的maxsum代码并提高时间复杂度?

huangapple go评论76阅读模式
英文:

How to optimize my maxsum code and improve time complexity?

问题

我在解决HackerRank问题(最大子数组和)。

最大子数组和问题

给定一个整数数组a和一个整数m,确定其任意子数组的和的最大值对m取模。

如何优化我的maxsum代码并提高时间复杂度?

我的代码运行正常,但应该针对更大的集合进行优化。

b=[]
def maximumSum(a, m):
    for i in range(len(a)):
        for j in range(len(a)):
            if j>=i:
                subarray = a[i:j+1]
                b.append(subarray)

    return max([sum(i)%m for i in b])

有什么想法?

英文:

I am working on HackerRank problem(maximum-subarray-sum).

maximum subarray sum problem

Given an element array of integers a and an integer m determine the maximum value of the sum of any of its subarrays modulo m.

如何优化我的maxsum代码并提高时间复杂度?

My code works fine, but should be optimized for larger sets.

b=[]
def maximumSum(a, m):
    for i in range(len(a)):
        for j in range(len(a)):
            if j>=i:
                subarray = a[i:j+1]
                b.append(subarray)

    return max([sum(i)%m for i in b])

Any ideas?

答案1

得分: 2

以下是您要翻译的内容:

Quadratic time, just like the accepted answer from prhmma, but simpler and faster. I just accumulate the array suffixes. Benchmark with several array lengths:

array length: 100
  0.64 ± 0.01 ms  Kelly
  1.71 ± 0.00 ms  prhmma
  4.55 ± 0.06 ms  original

array length: 500
 15.63 ± 0.02 ms  Kelly
 45.19 ± 0.20 ms  prhmma
341.87 ± 1.06 ms  original

array length: 1000
 62.12 ± 0.27 ms  Kelly
180.37 ± 0.23 ms  prhmma

Code ([Try it online!](https://tio.run/##jVRLbtswEN3rFASKwGSsGrLdFK0AZdNll12qgkFZVExXpASSam0EOVSv0Iu5w48sKUGCaGXO9817M@7O5tDK7ZdOXS4Vq9F31jRnTGMkSBoh@CjKEM3Twj1KeCTu158DbxiiPsZ@@uqyX90qdEJcTiOGKKzREp0IukFi5uM1uO9ROc8Y2uqrla66tsMJcQbFTK8kKqMosvBbxR@4pM10gjLLPXoLiltQisoHhhsmMSUknYE@vuEPII/3GX@JUfclVYqeHV08PS7Xxcs5VrTrmKzwEDybQdATznUvMCc3YgRbFiQM16mDEHQ6WqdYzU87SIK2eVKgW@RROy8UDC4vzL5Xiklztb2LlHkSnj6XdtJiLuSICFyQMIl/td@YM208orfEhFc8b0Ci18TjgG4To9fLv9FikpEfC/Tx2VBLoN/OHJqP6vkho7qXe7vnwy7G/qjioB8EqFYgwwXjBnHRtcqEl/doQw3XhkOR4BWMyhjsFfsdBRNMWbXQ7QP61gLDeyOZ1pElYTeSsJ3csE9Y7Q8t3zONfcA6ub39SmL0K9sk4aAsG87sXuzUQW0wuaFgw/z2heXj0uB68XgNelqQq8a1heGz1mkx8q6Y7htXcVLKgdSa2cGCPwu97Yg/OsYqdwKGaYOBC1f4egQWx@Kn9PcHkj@YQ7qIkfTFLbdWj8c6RXnxDNyTC7GlLe0a15MVMTYrN3BUa7Z1ecbmaeCfVdiVzeuC5OldUUzmc@sAtFjVsAGUn1eb@gn9@4senYTO9snZhEaL8Swmym3uJjjeIZ8ceZwL@FKO@QlYJfzy4YaKsqLpIAzw14uSqWxN5hlh7uG/zJBoLnrgxzUDbOycOWonA3nFBsJBzdVuJ6lgux3UchKvk2QQ2RvunhsgYrDYBSOXy38 "Python 3.8 (pre-release) – Try It Online")):

def Kelly(a, m):
    a = a[:]
    b = 0
    while a:
        s = 0
        for x in a:
            s = (s + x) % m
            if s > b:
                b = s
        a.pop(0)
    return b


def original(a, m):
    b=[]
    for i in range(len(a)):
        for j in range(len(a)):
            if j >= i:
                subarray = a[i:j+1]
                b.append(subarray)
    return max([sum(i)%m for i in b])


def prhmma(a, m):
    prefix_sum = [0] * len(a)
    max_sum = 0
    current_sum = 0

    for i in range(len(a)):
        current_sum = (current_sum + a[i]) % m
        prefix_sum[i] = current_sum

    for i in range(len(prefix_sum)):
        max_sum = max(max_sum, prefix_sum[i])

        for j in range(i + 2, len(prefix_sum)):
            max_sum = max(max_sum, (prefix_sum[j] - prefix_sum[i] + m) % m)

    return max_sum


funcs = original, Kelly, prhmma

from timeit import timeit
from statistics import mean, stdev
import random

# Correctness
for _ in range(3):
    a = random.choices(range(10**9), k=200)
    m = 10**9
    expect = funcs[0](a, m)
    print(f'{expect = }')
    for f in funcs[1:]:
        result = f(a, m)
        assert result == expect

# Speed
def test(n, funcs):
    print('\narray length:', n)
    times = {f: [] for f in funcs}
    def stats(f):
        ts = [t * 1e3 for t in sorted(times[f])[:5]]
        return f'{mean(ts):6.2f} ± {stdev(ts):4.2f} ms ';

    for _ in range(25):
        a = random.choices(range(10**9), k=n)
        m = 10**9
        for f in funcs:
            t = timeit(lambda: f(a, m), number=1)
            times[f].append(t)

    for f in sorted(funcs, key=stats):
        print(stats(f), f.__name__)

test(100, funcs)
test(500, funcs)
test(1000, funcs[1:])
英文:

Quadratic time, just like the accepted answer from prhmma, but simpler and faster. I just accumulate the array suffixes. Benchmark with several array lengths:

array length: 100
0.64 ± 0.01 ms  Kelly
1.71 ± 0.00 ms  prhmma
4.55 ± 0.06 ms  original
array length: 500
15.63 ± 0.02 ms  Kelly
45.19 ± 0.20 ms  prhmma
341.87 ± 1.06 ms  original
array length: 1000
62.12 ± 0.27 ms  Kelly
180.37 ± 0.23 ms  prhmma

Code ([Try it online!](https://tio.run/##jVRLbtswEN3rFASKwGSsGrLdFK0AZdNll12qgkFZVExXpASSam0EOVSv0Iu5w48sKUGCaGXO9817M@7O5tDK7ZdOXS4Vq9F31jRnTGMkSBoh@CjKEM3Twj1KeCTu158DbxiiPsZ@@uqyX90qdEJcTiOGKKzREp0IukFi5uM1uO9ROc8Y2uqrla66tsMJcQbFTK8kKqMosvBbxR@4pM10gjLLPXoLiltQisoHhhsmMSUknYE@vuEPII/3GX@JUfclVYqeHV08PS7Xxcs5VrTrmKzwEDybQdATznUvMCc3YgRbFiQM16mDEHQ6WqdYzU87SIK2eVKgW@RROy8UDC4vzL5Xiklztb2LlHkSnj6XdtJiLuSICFyQMIl/td@YM208orfEhFc8b0Ci18TjgG4To9fLv9FikpEfC/Tx2VBLoN/OHJqP6vkho7qXe7vnwy7G/qjioB8EqFYgwwXjBnHRtcqEl/doQw3XhkOR4BWMyhjsFfsdBRNMWbXQ7QP61gLDeyOZ1pElYTeSsJ3csE9Y7Q8t3zONfcA6ub39SmL0K9sk4aAsG87sXuzUQW0wuaFgw/z2heXj0uB68XgNelqQq8a1heGz1mkx8q6Y7htXcVLKgdSa2cGCPwu97Yg/OsYqdwKGaYOBC1f4egQWx@Kn9PcHkj@YQ7qIkfTFLbdWj8c6RXnxDNyTC7GlLe0a15MVMTYrN3BUa7Z1ecbmaeCfVdiVzeuC5OldUUzmc@sAtFjVsAGUn1eb@gn9@4senYTO9snZhEaL8Swmym3uJjjeIZ8ceZwL@FKO@QlYJfzy4YaKsqLpIAzw14uSqWxN5hlh7uG/zJBoLnrgxzUDbOycOWonA3nFBsJBzdVuJ6lgux3UchKvk2QQ2RvunhsgYrDYBSOXy38 "Python 3.8 (pre-release) – Try It Online")):

def Kelly(a, m):
a = a[:]
b = 0
while a:
s = 0
for x in a:
s = (s + x) % m
if s > b:
b = s
a.pop(0)
return b
def original(a, m):
b=[]
for i in range(len(a)):
for j in range(len(a)):
if j>=i:
subarray = a[i:j+1]
b.append(subarray)
return max([sum(i)%m for i in b])
def prhmma(a, m):
prefix_sum = [0] * len(a)
max_sum = 0
current_sum = 0
for i in range(len(a)):
current_sum = (current_sum + a[i]) % m
prefix_sum[i] = current_sum
for i in range(len(prefix_sum)):
max_sum = max(max_sum, prefix_sum[i])
for j in range(i + 2, len(prefix_sum)):
max_sum = max(max_sum, (prefix_sum[j] - prefix_sum[i] + m) % m)
return max_sum
funcs = original, Kelly, prhmma
from timeit import timeit
from statistics import mean, stdev
import random
# Correctness
for _ in range(3):
a = random.choices(range(10**9), k=200)
m = 10**9
expect = funcs[0](a, m)
print(f'{expect = }')
for f in funcs[1:]:
result = f(a, m)
assert result == expect
# Speed
def test(n, funcs):
print('\narray length:', n)
times = {f: [] for f in funcs}
def stats(f):
ts = [t * 1e3 for t in sorted(times[f])[:5]]
return f'{mean(ts):6.2f} ± {stdev(ts):4.2f} ms '
for _ in range(25):
a = random.choices(range(10**9), k=n)
m = 10**9
for f in funcs:
t = timeit(lambda: f(a, m), number=1)
times[f].append(t)
for f in sorted(funcs, key=stats):
print(stats(f), f.__name__)
test(100, funcs)
test(500, funcs)
test(1000, funcs[1:])

Probably it can be done in sub-quadratic time, but you accepted quadratic time already, and the testing/benchmark code can still be useful when someone comes up with something faster.

huangapple
  • 本文由 发表于 2023年6月25日 19:47:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76550238.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定