简体   繁体   English

Python 时间复杂度将 O(n^2) 代码转换为 O(n)

[英]Python time complexity convert O(n^2) code to O(n)

The recursive function dumbo_func, which has been preloaded into the answer box, has O(n^2) performance.已经预加载到答案框中的递归 function dumbo_func 具有 O(n^2) 性能。 Rewrite it (still using recursion) so that its performance becomes O(n).重写它(仍然使用递归),使其性能变为 O(n)。 Your function will be tested in a loop calling it 20 times with a list of up to 10,000 elements and will time out if the function is still O(n^2 ).您的 function 将在一个循环中进行测试,调用它 20 次,并使用最多 10,000 个元素的列表,如果 function 仍为 O(n^2),则会超时。

Note that the function is preceded by code to increase the maximum recursion depth.请注意,function 前面是增加最大递归深度的代码。 You will need to include that code when doing your own testing and when submitting your answer.在进行自己的测试和提交答案时,您需要包含该代码。 However, under Microsoft Windows you'll probably crash the Python interpreter if you try lists of more than about 2000 elements.但是,在 Microsoft Windows 下,如果您尝试包含超过 2000 个元素的列表,您可能会使 Python 解释器崩溃。 On a lab machine or on the quiz server, a list size of 10,000 will be fine, provided you've made the necessary change to the code so it's O(n) rather than O(n2).在实验室机器或测验服务器上,列表大小为 10,000 就可以了,前提是您对代码进行了必要的更改,使其为 O(n) 而不是 O(n2)。

import sys
sys.setrecursionlimit(100000)

def dumbo_func(data):
    """Takes a list of numbers and does weird stuff with it"""
    if len(data) == 0:
        return 0
    else:
        if (data[0] // 100) % 3 != 0:
            return 1 + dumbo_func(data[1:])
        else:
            return dumbo_func(data[1:])

#Test1
#Simple test with short list.
#Original func works fine on this
#Result: 3
data = [677, 90, 785, 875, 7, 90393, 10707]  
print(dumbo_func(data)) 


#Test2
#This test will timeout with a O(n^2) function
#Result: Yay!
ok = True
for i in range(20):
    # Repeat enough times to ensure timeout on O(n^2)
    data = list(range(10_000))
    right_ans = secret_version(data)
    your_ans = dumbo_func(data)
    if your_ans != right_ans:
        print("Sorry, but no banana")
        ok = False
        break
if ok:
    print("Yay!")

I wrote my code as below which pass test1 but doesn't pass test2.我编写了如下代码,它通过了 test1 但没有通过 test2。 Isn't my code O(n)?我的代码不是 O(n) 吗? Please advise where inappropriate.不合适的地方请指教。

import sys
sys.setrecursionlimit(100000)

def dumbo_func(data):
    """Takes a list of numbers and does weird stuff with it"""
    if len(data) == 0:
        return 0
    else:
        return int((data[0] // 100) % 3 != 0) + dumbo_func(data[1:])

Here's a simple guide on list slicing.这是列表切片的简单指南。 Long story short, the recursive function is O(N^2) because slicing the list each time to call the function recursively takes O(N) time per each slice.长话短说,递归 function 是O(N^2) ,因为每次对列表进行切片以递归地调用 function 每个切片需要O(N)时间。

Solution: try sending the index of the first element of the subarray you're considering to the recursive function, rather then sending the entire sliced array as an argument.解决方案:尝试将您正在考虑的子数组的第一个元素的索引发送到递归 function,而不是将整个切片数组作为参数发送。

Hint: def func(data, index_of_first_element) rather than def func(data)提示: def func(data, index_of_first_element)而不是def func(data)

I tried sending the index to the subarray but the time limit exceed for [0]*10000我尝试将索引发送到子数组,但时间限制超过 [0]*10000

import sys
sys.setrecursionlimit(100000)

def dumbo_func(data, start_index=0):
    """Takes a list of numbers and does weird stuff with it"""
    if len(data) - start_index == 0:
        return 0
    else:
        if (data[start_index] // 100) % 3 != 0:
            return 1 + dumbo_func(data, start_index+1)
        else:
            return dumbo_func(data, start_index+1)

data = [677, 90, 785, 875, 7, 90393, 10707]
print(dumbo_func(data))
data = [0]*10000 
print(dumbo_func(data))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM