📅  最后修改于: 2023-12-03 14:55:43.414000             🧑  作者: Mango
在数论中,一个三角形数可以表示为一个等差数列的和,而这个等差数列的公差为1。可表示为以下公式:
$$T_n = \frac{n(n+1)}{2}$$
例如:
T1 = 1
T2 = 1 + 2 = 3
T3 = 1 + 2 + 3 = 6
T4 = 1 + 2 + 3 + 4 = 10
T5 = 1 + 2 + 3 + 4 + 5 = 15
我们的目标是检查一个数是否可以表示为两个三角形数的和。
最简单粗暴的思路是枚举每对三角形数 $T_i$ 和 $T_j$。时间复杂度为 $O(n^2)$。两个三角形数的和可以表示成如下的表达式:
$$T_i + T_j = \frac{i(i+1)}{2} + \frac{j(j+1)}{2} = \frac{(i+j)(i+j+1)}{2}$$
def check_triangle_number(n):
for i in range(1, n+1):
for j in range(1, n+1):
if (i*(i+1) + j*(j+1))//2 == n:
return True
return False
$O(n^2)$
上面的方法虽然可以达到目的,但时间复杂度实在是太高了。我们可以用双指针法来解决这个问题。首先确定最小的三角形数 $T_i$,这里我们可以简单的将 $T_i = 1$,然后另外一个三角形数 $T_j$ 从 $T_{i+1}$ 开始。如果这个和小于 $n$,则 $T_j$ 指针向右移动,如果这个和大于 $n$,则 $T_i$ 指针向右移动。
def check_triangle_number(n):
i, j = 1, 1
while i*(i+1)//2 < n:
while j*(j+1)//2 < n:
s = i*(i+1)//2 + j*(j+1)//2
if s == n:
return True
elif s > n:
break
j += 1
i += 1
j = i
return False
$O(n)$
以上两种方法都可以检查一个数是否可以表示为两个三角形数的和,但双指针法更加高效。