提高性能(超时错误)

时间:2017-08-03 16:20:39

标签: algorithm python-2.7 performance

问题

您将获得一组S = {1,2,3...N}。从集合A中找到两个整数BS,以使&的值尽可能最大且小于给定的整数K。在这种情况下,&表示运算符按位AND。

2 <= N <= 10^3
2 <= K <= N

解决方案

#Brute force
testCases = int(raw_input())
while testCases > 0:
    n_k = raw_input().split()
    n = range(1, int(n_k[0]) + 1) #THIS IS THE RANGE S
    k = int(n_k[1])
    max_pair = -1
    for x in n[:len(n)-1]:
        for y in n[x:]:
            x_y = x & y
            if( x_y < k):
                max_pair = max(max_pair, x_y)
print max_pair
testCases -= 1

问题

我已经开始讨论如何改进此代码,但我无法得出答案。当N很长时,我收到超时错误。任何人都可以指出我正确的方向来弄清楚如何改进这些代码?我无法想出缩短循环的方法,我可以使用什么标准?按位&amp; 会让您丢失信息,但它不是一种可逆的方法(就像您添加时一样,为了让它减去...)。

我的思路:

  • (A&amp; B)&lt; K
  • 我从第一个循环中知道A,如何让第二个循环迭代次数减少?
  • (A&amp; B)= 1 ...(k-1)
  • 如何在世界范围内将B移动到等式的另一边,以便我可以在第二个循环中更快地丢弃数字?

编辑:解决方案

我肯定在笑这个。感谢用户@ead,我在那里学到了更快的Python解释器,所以不要选择&#34; Python 2&#34;我选择了&#34; Pypy 2&#34; ...所有测试用例都快速通过,没有时间错误。哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈!

对于LOL,我继续前进并将代码翻译为使用JS(Node.js)并且低并且看到......不是超时错误。如果有人想要JS中的代码,那么它就是。

function processData(input) {
    var data = input.split("\n");
    var testCases = parseInt(data[0]);
    var n_k, n, k, max_pair;
    for(let index=1; index<data.length; ++index){
        n_k = data[index].split(" ");
        n = getSet( parseInt(n_k[0]) ),
        k = parseInt(n_k[1]);
        max_pair = 0;
        n.forEach(function(a){
            for(let i=a; i<n.length; ++i){
                let a_b = a & n[i];
                if(a_b < k)
                    max_pair = Math.max(max_pair, a_b);
            }
        });
        console.log(max_pair);
    }
}

function getSet(n){
    var n_set = [];
    for(let index=1; index<=n; ++index)
        n_set.push(index);
    return n_set;
}

2 个答案:

答案 0 :(得分:1)

您可以从最高位向下构建结果。在每个点上,您可以测试是否有一对数字&lt; = n且设置了给定的位。

您可以观察到,如果nr是给定的数字,那么nr|(nr+1)是与nr不同的最小数字,至少相同的位设置为nr。< / p>

def maxpair(n, k):
    result = 0
    for bit in xrange(63, -1, -1):
        nr = result | (1<<bit)
        if nr < k and (nr|(nr+1)) <= n:
            result = nr
    return result

这适用于O(log n)时间[如果你稍微概括一下代码,用结果中的位数代替64],这对于可笑的大n来说足够快。

可以通过比较天真但明显正确的解决方案来检查正确性。

def maxpair_slow(n, k):
    best = 0
    for a in xrange(1, n+1):
        for b in xrange(a+1, n+1):
            if (a&b) < k:
                best = max(best, a&b)
    return best

for N in xrange(100):
    for K in xrange(2, N):
        m1 = maxpair(N, K)
        m2 = maxpair_slow(N, K)
        if m1 != m2:
            print N, K, m1, m2

还有O(1)解决方案,因为解决方案始终是K-1,K-2或K-3,只需测试这三种可能性:

def maxpair2(n, k):
    return next(i for i in (k-1,k-2,k-3) if i|(i+1)<=n)

答案 1 :(得分:0)

我认为没有什么特别的,只是CPython对于整数运算来说非常慢。用C / C ++编写,你的程序非常快,每次循环不需要超过0.01秒。

在竞争编程中,很多问题从来都不是用CPython来解决的,而是使用PyPy,它有一个更快的整数运算和一个git编译器,但其他方面都是一个python解释器,就像CPython一样。

所以,只要有可能,就在比赛中选择PyPy。