提高后续算法

时间:2017-12-09 11:26:40

标签: algorithm python-3.x

问题: -

input = n
output :-

1     2      3.......n [first row]
2n+1 2n+2   2n+3....3n [second row]

3n+1  3n+2   3n+3...4n [second last row]
n+1   n+2    n+3....2n [last row]

在问题中我们必须打印一个正方形,使得我们的正方形中有'n'行数,并且在每一行中我们都有'n'个数字。我们从1到正方形(n)的数字准备行,这样我们填充第一行的数字,然后填充最后一行,第二行,第二行等等......

例如如果n = 4
我们从1打印到4开始然后打印换行,所以我们的第一行是: -

1 2 3 4     

然后我们的最后一行是继续

5 6 7 8    

然后我们的第二行将是

9 10 11 12                                                         

几个例子:

input = 1
output = 1

input = 2
output = 1 2
         3 4

input = 3
output = 1 2 3
         7 8 9
         4 5 6

我的代码:

n = int(input().strip())
lines = [i for i in range (1, n + 1)]


line_order1 = []
line_order2 = []

#Reordering lines so we know the staring element of our method
for i in lines:
    if(i % 2 == 1):
        line_order1.append(i)
    else:
        line_order2.append(i)

 print(line_order1)
 print(line_order2)

 // Getting the desired order of lines
 line_order2.reverse()
 line_order1.extend(line_order2)
 print(line_order1)

 // Now printing the desired square 
 for l in line_order1:
     for i in range (1, n+1):
         k = n * (l - 1)
         print(k + i, end = " ")
     print("\n")

在执行时间方面有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

虽然我看到一些小的地方可以改进你的代码,但性能可能不会好得多(我的建议可能根本不会使任何性能差异)。您的代码将花费O(n**2)时间,这是您可以做的最好的时间,因为您需要打印出那么多数字才能形成您的方块。即使你将一些更长,更冗长的步骤组合成更紧凑的版本,它们也只能通过一个常数因子来改善。

我的第一个建议是将行从0编号为n-1,而不是从1n。当您必须计算要包含在行的值中的n倍数时,这将为您节省一些精力。目前,您的计算中有一个尴尬的l - 1,如果您只是为行使用零索引数字,则可以跳过。 (另外l是一个可怕的变量名,因为它看起来像某些字体中的数字1(一个)。)

我的下一个建议是简化构建订单的代码。你不需要三个列表,你可以用一个列表来完成整个事情,你可以提供两个range个对象,每个对象向上或向下计数两个。

line_order = list(range(0, n, 2)) # count up by twos
line_order.extend(range(n - 1 - n%2, 0, -2)) # count down starting at either n-1 or n-2

或者,如果您愿意使用标准库模块,可以import itertools然后使用:

line_order = itertools.chain(range(0, n, 2), range(n - 1 - n%2, 0, -2))

itertools.chain函数返回一个迭代器,它从每个可迭代参数中产生值,就好像它们被连接在一起一样,没有制作任何数据副本或使用大量额外内存。这里的差异可能不大(因为您可以有效地打印出来的最大n相当小),但是如果您使用此算法的结果执行了不同的操作并且n在数十亿,避免用这么多值填充列表是非常好的。

我的最后一个建议是再次使用range直接生成每行中的所有数字,而不是从1显式循环到n并添加k每个时间。

for row_num in line_order:
    print(*range(n * row_num + 1, n * (rownum + 1) + 1))

您可以使用已包含的n的倍数计算起点和终点,而不是需要在每个单独的步骤中执行此操作。您当然不需要像往常一样经常重新计算k。您可以使用可迭代解包语法(print)一次性将范围中的所有值传递到*args

请注意,以这种方式解压缩范围与之前关于itertools.chain的建议相反。如果n很大,则使用range上的循环会提高内存效率,因为您不希望所有n值同时存在于内存中。这是什么样子:

for line_num in line_order:
    for value in range(n * row_num + 1, n * (rownum + 1) + 1):
        print(value, end=" ")
    print()