Google CodeJam过去练习 - 减少运行时间

时间:2016-09-03 13:54:22

标签: python algorithm

我从2010年开始研究过去的Google Codejam算法,但时间复杂度非常糟糕。

以下是来自Google Codejam的问题:https://code.google.com/codejam/contest/619102/dashboard

TLDR - 想象一下两个塔的两侧有一条数字线,我们从一个建筑物数字线(比如从10)到另一个建筑物数字线上的另一个点(从1开始)画一条线。如果我们这样做n次,那些线会相交多少次?

我想知道这里是否有人能够提出一种方法可以加快我的算法速度? 4个小时后我真的看不到一个,我失去了我的miinnnnddd。

这是我现在的代码。

示例输入是:

2 - (案件数量)

3 - (#1中的导线数量)

1 10

5 5

7 7

案例#1:2 - (第1,10,5,5,7,7行之间的2个交叉点)

2 - (情况#2中的导线数量)

5 5

2 2

案例#2:0 - (没有线相交)

def solve(wire_ints, test_case):
    answer_integer = 0
    for iterI in range(number_wires):
        for iterJ in range(iterI):
            holder = [wire_ints[iterI], wire_ints[iterJ]] 
            holder.sort()
            if holder[0][1] > holder[1][1]:
                answer_integer = answer_integer + 1
    return("Case #" + str(test_case) + ":" + " " + str(answer_integer))

for test_case in range(1, int(input()) + 1):
  number_wires = int(input())
  wire_ints = []
  for count1 in range(number_wires):
    left_port,right_port = map(int, input().split())
    wire_ints.append((left_port,right_port))
  answer_string = solve(wire_ints, test_case)
  print(answer_string)

这个算法对我给它的任何输入都有效,但正如我所说的非常难看和慢。

帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

由于N为1000,因此可以接受O(N^2)的算法。所以你要做的就是用一个端点对电线进行排序。

//sorted by first number
1 10    
5 5
7 7

然后从头开始处理每一行,并检查它是否与之前的行相交。如果它之前的一条线的第二个端点大于当前线的第二个点,则它们具有交点。这需要两个循环,因此O(N^2)复杂度足以满足N=1000。您也可以将其解释为反转计数。你必须计算列表按第一个终点排序的第二个终点的反转次数。

10 5 7 ->‌ number of inversions is 2, because of (10,5) and (10,7)

还有O(NlogN) approach来计算您对此问题不需要的反转次数。