HackerRank Sherlock和Array性能

时间:2016-04-20 11:51:45

标签: python performance python-3.x

我在HackerRank Sherlock和Array测试中做了这个小算法,但这在2个测试用例中得到了超时。这些测试用例创建了大量列表,我无法看到性能方面的错误。

这是问题所在:

Watson给Sherlock一个长度为NN的阵列AA。然后他要求他确定数组中是否存在一个元素,使其左边的元素总和等于其右边元素的总和。如果左/右没有元素,则总和被认为是零。 正式地,找到一个ii,这样,AA1 + A + A2 ... A ... Ai-1 = A = Ai + 1 + A + Ai + 2 ... A ... AN。

输入格式 第一行包含TT,测试用例的数量。对于每个测试用例,第一行包含NN,即阵列AA中的元素数。每个测试用例的第二行包含NN空格分隔的整数,表示数组AA。

输出格式 对于每个测试用例,如果数组中存在元素,则打印YES,以使其左侧元素的总和等于其右侧元素的总和;否则打印NO。

这是我的代码:

for turn in range(int(input())):
    lst_size = int(input())
    has_equal = False

    lst = list(map(int, input().split(" ")))

    if lst_size > 2:

        for i in range(lst_size):
            sumleft = sum(lst[:i])
            sumright = sum(lst[(i+1):])

            if sumleft == sumright:
                has_equal = True
                break

    if has_equal:
        print("YES")
    else:
        print("NO")

3 个答案:

答案 0 :(得分:1)

总和成本就像迭代一样,你必须只做一次并且只需要总和。例如,您可以从列表的中心开始:

def test_list(lst):
    i = len(lst)/2
    sumleft = sum(lst[:i])
    sumright = sum(lst[i+1:])

    if sumleft==sumright:
        print "YES",i

    elif sumleft<sumright:
        print "going right"
        while(True):
            if sumleft==sumright:
                print "YES",i
                break
            if i==len(lst)-1 or sumleft>sumright :
                print "NO",i
                break
            sumleft += lst[i]
            sumright -= lst[i+1]
            i+=1

    else:
        print "going left"
        while(True):

            if sumleft==sumright:
                print "YES",i
                break
            if i==0 or sumleft<sumright :
                print "NO",i
                break
            sumright += lst[i]
            sumleft -= lst[i-1]
            i-=1



lst = [40,1,5,4,6,3,2,1,4,8,7,3,81]
test_list(lst)

结果:

> going right
> YES 11

答案 1 :(得分:0)

我可以通过不对每次迭代进行求和来改进代码并且它可以工作:

for turn in range(int(input())):
      lst_size = int(input())

      has_equal = False

      lst = list(map(int, input().split(" ")))

      sumleft = 0
      total = sum(lst)

      for i in range(1, lst_size):
           sumright = 0
           sumleft += lst[i-1]
           sumright = total - sumleft - lst[i]

           if sumleft == sumright:
               has_equal = True
               break

    if has_equal or lst_size == 1:
        print("YES")
    else:
        print("NO")

答案 2 :(得分:0)

我在O(n)时间内解决了这个问题,所有测试用例都通过了。 您可以通过使用一些数学来驱动求解方程。

假设我们有一个数组,它是随机数组{3,7,5,10,2,7,4,2},因此,该元素存在使得所有元素左侧的和等于右边所有元素的总和。

我假设元素由y表示,并且它存在于某处之间。因此,元素的某些左侧用x表示,因为我说过朝向左侧的所有元素的总和等于朝向该元素右侧的所有元素的总和。因此右侧的总和也可以用x表示。因此,我们可以很容易地说数组中存在的所有元素的总和应等于x + y + x。

x + y + x =所有元素的总和

2 x + y =所有元素的总和

2 x =所有元素的总和-y ---> eq 1

如果我们有x和y使得该等式成立。这意味着存在一个正确的元素,因为在此等式中,我们必须未知x和y。因此我们必须首先获取x和y的值,然后将这两个值都放在等式中,然后查看LHS是否等于RHS? LHS等于RHS,这意味着数组中存在某个元素,其中所有元素的总和朝向该元素的左侧等于该元素的右侧。让我们以一个示例数组为例。

{3,7,5,10,2,7,4,2}

首先,我将计算所有元素的总和。

所有元素之和= 3 + 7 + 5 + 10 + 2 + 7 + 4 + 2所有元素之和= 40

将其替换为等式1,那么您将得到等式以下

2x = 40-y -> eq 2

因为我们不知道y,但是可以肯定的是y将属于数组中存在的任何元素之一。因此将一次从数组中取出一个元素,并将y也替换为类似于x的那个元素。我们将基于y取x值,无论它来自何处,并替换此问题,并查看LHS是否等于RHS。如果我们发现LHS等于RHS的x和y对。这意味着,我们在数组中具有该条件成立的元素,并且将返回YES。

第一次迭代-{3,7,5,10,2,7,4,2}

y = 3,x = 0

只需替换等式2中的两个值,就可以播种

0不等于37

现在将指针向前移动

y = 7,x = 0 + 3 = 3

只需替换等式2中的两个值,就可以播种

6不等于33

.... so,直到找到满足此条件的元素y为止。

现在跳过下一步,使用y = 5进行迭代,并尝试让y = 10知道

如果y = 10,x = 3 + 7 + 5 = 15

只需替换等式2中的两个值,就可以播种

30等于30。这意味着我们正在寻找的元素(y),其中左总和等于右总和。

这是通过100%测试用例的代码。

static String balancedSums(List<Integer> arr) {
        int x = 0;
        int sum = 0;
        for (int a : arr) {
            sum += a;
        }

        for (int y : arr) {
            if (2 * x == sum - y) {
                return "YES";
            }
            x = x + y;
        }
        return "NO";

    }

仍然有疑问,您可以查看视频教程here