📜  在竞争性编程中避免在Python中使用TLE

📅  最后修改于: 2021-06-26 13:31:46             🧑  作者: Mango

获得TLE的原因

  • 与其他编程语言相比,它速度较慢。
  • 它提供较慢的输入/输出。
  • 它具有较低的递归深度,通常使TLE出现在递归和图形问题中。

使用Python避免TLE的提示

转换为迭代方法

  • 任何递归问题都可以转换为迭代方法,因此请尝试使用迭代方法代替递归。
  • 使用Stack和while循环可以节省程序的执行时间。

程序1:

下面给出的代码显示了在两种方法中计算数字阶乘所需的时间:

Python3
# Program to show the time taken in
# iteration and recursion
  
import time
  
# Recursive function to find factorial
# of the given number N
def factorial(N):
    
      # Base Case
    if N == 0:
        return 1
        
    # Recursive Call
    return N * factorial(N - 1)
  
# Driver Code
if __name__ == '__main__':
    n = 20
  
    # Find the time taken for the
    # recursive approach
    start = time.perf_counter()
    print("Calculated using recursion: ", factorial(n))
      
    end = time.perf_counter()
    print("Time taken in recursion: ", "{0:.9f}".format(end-start))
  
    # Find time taken for iterative
    # approach
    start = time.perf_counter()
    result = 1
      
    while n > 0:
        result *= n
        n -= 1
          
    print("Calculated using the iterative method: ", result)
      
    end = time.perf_counter()
    print("Time taken in iteration: ", "{0:.9f}".format(end-start))


Python3
# Python3 program to explain the 
# sys.setrecursionlimit() method
  
import sys
  
# Print the current recursion limit
# using sys.getrecursionlimit()
print("Original recursion limit was: ")
print(sys.getrecursionlimit())
  
# Set a new recursion limit
sys.setrecursionlimit(10**6)
  
# Print the new recursion limit
print("New recursion limit is: ")
print(sys.getrecursionlimit())


Python3
# Program to show time taken in fast
# I / O and normal I / O in python
from sys import stdin, stdout
import time
  
# Function for fast I / O
def fastIO():
  
    # Stores the start time
    start = time.perf_counter()
  
    # To read single integer
    n = stdin.readline()
  
    # To input array
    arr = [int(x) for x in stdin.readline().split()]
  
    # Output integer
    stdout.write(str(n))
  
    # Output array
    stdout.write(" ".join(map(str, arr)) + "\n")
  
    # Stores the end time
    end = time.perf_counter()
    print("Time taken in fast IO", end-start)
  
# Function for normal I / O
def normalIO():
  
    # Stores the start time
    start = time.perf_counter()
  
    # Input integer
    n = int(input())
  
    # Input array
    arr = [int(x) for x in input().split()]
  
    # Output integer
    print(n)
  
    # Output array
    for i in arr:
        print(i, end =" ")
    print()
  
    # Stores the end time
    end = time.perf_counter()
    print("Time taken in normal IO: ", end-start)
  
  
# Driver Code
if __name__ == '__main__':
    fastIO()
    normalIO()


Python3
# Python program to demonstrate
# use of list comprehension
  
import time
  
start = time.perf_counter()
l = []
  
# Slower
for i in range(100):
    l.append(i)
end = time.perf_counter()
t1 = end-start
  
start = time.perf_counter()
  
# Faster
m = [i for i in range(100)]
end = time.perf_counter()
t2 = end-start
  
# Comparing the time
if t2 < t1:
    print("Initialising the list with ", end ="")
    print("list comprehension is faster")


输出:
Calculated using recursion:  2432902008176640000
Time taken in recursion:  0.000015925
Calculated using the iterative method:  2432902008176640000
Time taken in iteration:  0.000009279

设置递归限制

  • 使用sys.setrecursionlimit()将Python解释器堆栈的最大深度设置为程序所需的整数值。
  • 如果在当前递归深度下新的限制太低,它将引发递归错误异常

程式2:

下面是说明sys.setrecursionlimit()方法的用法的程序:

Python3

# Python3 program to explain the 
# sys.setrecursionlimit() method
  
import sys
  
# Print the current recursion limit
# using sys.getrecursionlimit()
print("Original recursion limit was: ")
print(sys.getrecursionlimit())
  
# Set a new recursion limit
sys.setrecursionlimit(10**6)
  
# Print the new recursion limit
print("New recursion limit is: ")
print(sys.getrecursionlimit())
输出:
Original recursion limit was: 
1000
New recursion limit is: 
1000000

始终使用更快的输入/输出

想法是使用stdinstdout进行快速输入和输出。

程序3:

下面的程序演示了stdin和stdout花费的时间:

Python3

# Program to show time taken in fast
# I / O and normal I / O in python
from sys import stdin, stdout
import time
  
# Function for fast I / O
def fastIO():
  
    # Stores the start time
    start = time.perf_counter()
  
    # To read single integer
    n = stdin.readline()
  
    # To input array
    arr = [int(x) for x in stdin.readline().split()]
  
    # Output integer
    stdout.write(str(n))
  
    # Output array
    stdout.write(" ".join(map(str, arr)) + "\n")
  
    # Stores the end time
    end = time.perf_counter()
    print("Time taken in fast IO", end-start)
  
# Function for normal I / O
def normalIO():
  
    # Stores the start time
    start = time.perf_counter()
  
    # Input integer
    n = int(input())
  
    # Input array
    arr = [int(x) for x in input().split()]
  
    # Output integer
    print(n)
  
    # Output array
    for i in arr:
        print(i, end =" ")
    print()
  
    # Stores the end time
    end = time.perf_counter()
    print("Time taken in normal IO: ", end-start)
  
  
# Driver Code
if __name__ == '__main__':
    fastIO()
    normalIO()
输出:
Initialising the list with list comprehension is faster

输出:

使用PyPy2,因为它比Python2和Python3快

  • PyPy是CPython的Python的替代实现(这是标准实现)。
  • PyPy通常比CPython运行得快,因为PyPy是即时编译器,而CPython是解释器。
  • PyPy的最新版本是PyPy2.7 ,这是一个解释器,支持Python 2.7的语法和功能。
  • PyPy 3.6是beta版本, PyPy2.7 现在应该选择PyPy3 ,因为PyPy3也比Python3慢一些。

有用的提示

  1. 使用集合 deque,因为它为两端的append()pop()操作提供了O(1)时间复杂度。
  2. 列表理解比for循环快。
  3. 用列表理解来初始化列表比以后附加元素更好。

计划4:

下面的程序演示了列表理解的使用:

Python3

# Python program to demonstrate
# use of list comprehension
  
import time
  
start = time.perf_counter()
l = []
  
# Slower
for i in range(100):
    l.append(i)
end = time.perf_counter()
t1 = end-start
  
start = time.perf_counter()
  
# Faster
m = [i for i in range(100)]
end = time.perf_counter()
t2 = end-start
  
# Comparing the time
if t2 < t1:
    print("Initialising the list with ", end ="")
    print("list comprehension is faster")
输出:
Initialising the list with list comprehension is faster