C# 优化(降低复杂性)。从n边长度计算锐角三角形、直角三角形和钝角三角形
编辑1:将约束中的104更改为10^4。抱歉弄错了。 问题陈述: 我们有N根棍子。第i根棍子的大小是Ai。我们想知道从一根不同的棍子上每边创建的不同类型三角形的数量。计算锐角三角形、直角三角形和钝角三角形的数量 输入格式: 第一行包含N。 第二行包含N个整数。第i个数字表示Ai 约束条件:C# 优化(降低复杂性)。从n边长度计算锐角三角形、直角三角形和钝角三角形,c#,.net,algorithm,time-complexity,C#,.net,Algorithm,Time Complexity,编辑1:将约束中的104更改为10^4。抱歉弄错了。 问题陈述: 我们有N根棍子。第i根棍子的大小是Ai。我们想知道从一根不同的棍子上每边创建的不同类型三角形的数量。计算锐角三角形、直角三角形和钝角三角形的数量 输入格式: 第一行包含N。 第二行包含N个整数。第i个数字表示Ai 约束条件: For full score: 3≤N≤5000 For 40% score: 3≤N≤500 6 2 3 9 10 12 15 2 1 4 对于所有测试用例: 1≤A[i]≤10^4 A[i]
For full score: 3≤N≤5000
For 40% score: 3≤N≤500
6
2 3 9 10 12 15
2 1 4
对于所有测试用例:
1≤A[i]≤10^4
A[i]<A[i+1] where 1≤i<N
acute = 0
right = 0
obtuse = 0
a = sorted(a) # copy and convert to a list
a.append(2 * a[-1]) # add a sentinel equal to twice the max
for i in range(len(a) - 3): # exclude the sentinel
if a[i] <= 0:
continue
ka = i + 2
kr = i + 2
ko = i + 2
for j in range(i + 1, len(a) - 2): # i < j, exclude the sentinel
ka = max(ka, j + 1)
while a[i] ** 2 + a[j] ** 2 > a[ka] ** 2:
ka += 1
acute += ka - (j + 1)
kr = max(kr, ka)
while a[i] ** 2 + a[j] ** 2 == a[kr] ** 2:
kr += 1
right += kr - ka
ko = max(ko, kr)
while a[i] + a[j] > a[ko]:
ko += 1
obtuse += ko - kr
输出:
For full score: 3≤N≤5000
For 40% score: 3≤N≤500
6
2 3 9 10 12 15
2 1 4
可能的三角形是:
For full score: 3≤N≤5000
For 40% score: 3≤N≤500
6
2 3 9 10 12 15
2 1 4
锐角三角形
10−12−15, 9−10−十二,
直角三角形
9−12−十五
钝角三角形
2.−9−10, 3−9−10, 3−10−12, 9−10−十五
我想知道一种更有效的方法来解决这个问题,这样我就可以在给定的n(~5000)时限内执行它。
在我试图找到复杂性之后,我提出了O(n^3)。我不擅长处理复杂问题。我可能错了。我想用一种更有效的方法来解决这个问题。您可以通过以下方式来改进该方法:首先,按棒的长度对所有棒进行排序。之后,迭代每对棒(即具有平方复杂度的双循环)。对于每一对,执行一次搜索,以找到从锐角三角形切换到直角三角形的棍棒阵列中的位置(考虑预选的两个棍棒和作为基础的第三个棍棒)。然后执行另一个二进制操作,以找到将形状向右转换为钝角三角形的位置。在此之后,您将不得不执行另一个二进制搜索,以找到第三根棍子太长以至于无法与其形成有效三角形的位置。你将不得不处理一个以上的情况-如果没有直角三角形,你从锐角直接切换到钝角(这可以通过添加一个if来实现) 重要的是要注意,三角形的类型是由与三角形最大边相对的角度来确定的,因此在上述算法中,你只应该考虑比两个预先选定的杆大的边长(可以用另一个二进制来完成)。
总的来说,我提出的方法的复杂性为O(N2*log(N)),这比您的算法要好。目前我没有看到降低复杂性的方法,但您可以对代码进行一些加速
- 预先计算
的平方,而不是反复计算它们A[i]
- 如果按照示例中的顺序对长度进行排序(如果没有排序),则可以在第一次违反条件
时退出while循环A[i]+A[j]>A[k]
- 将
和n-1
的值存储在变量中,而不是反复计算它们(可能已经由编译器优化)n-2
- 不要计算
两次,将结果存储在变量中square(A[i])+square(A[j])
- 更改检查条件的顺序。直角三角形的可能性较小。总是先检查最常见的情况
- 对于整数值,使用
可能比使用a*a
square(a)
使用系统;
命名空间代码风暴
{
类计数三角形
{
公共静态双正方形(整数x)
{
返回Math.Pow(x,2);
}
静态void Main(字符串[]参数)
{
int n=int.Parse(Console.ReadLine());
字符串[]A_temp=Console.ReadLine().Split(“”);
int[]A=Array.ConvertAll(A_temp,Int32.Parse);
//TODO:对[]排序(如果尚未始终排序)
//TODO:创建平方值的数组E
int[]Asquares=。。。。
int n_m_2=n-2;
int n_m_1=n-1;
int锐=0,右=0,钝=0;
for(int i=0;i
只是一个小小的提示:Math.Pow()计算正方形相当慢。你应该修改你的方法:
public static double square(int x)
{
return x * x;
}
有两件事几乎肯定会有所改善:
x*x
而不是将其转换为双倍,然后调用Pow
,以加快平方速度i
计算一次平方,每j
计算一次平方,每k
计算一次平方这可以在时间
O(N²)
中解决。如有必要,对尺寸进行逐级排序
设三角形的边为a=a[k]
,b=a[j]
,c=a[i]