如何知道我们的数组中存在三角形三元组?
我被困在解决以下面试练习问题中:
我必须编写一个函数:
int triangle(int[] A);
给定一个由 N
个整数组成的零索引数组 A,如果存在一个三元组(P、Q、R),使得 1
则返回 1
代码>0 < P< Q< R< N。
A[P] + A[Q] > A[R],
A[Q] + A[R] > A[P],
A[R] + A[P] > A[Q].
如果这样的三元组不存在,该函数应返回0
。假设 0 < N< 100,000。假设数组的每个元素都是
[-1,000,000..1,000,000]
范围内的整数。
例如,给定数组 A
,
A[0]=10, A[1]=2, A[2]=5, A[3]=1, A[4]=8, A[5]=20
函数应返回 1
,因为三元组 (0, 2, 4)
满足所有要求状况。
对于数组 A
,
A[0]=10, A[1]=50, A[2]=5, A[3]=1
函数应返回 0
。
如果我执行三重循环,这将非常非常慢(复杂度:O(n^3)
)。我想也许可以用来存储数组的额外副本并对其进行排序,并对特定数字使用二分搜索。但我不知道如何解决这个问题。
有什么想法吗?
I was stuck in solving the following interview practice question:
I have to write a function:
int triangle(int[] A);
that given a zero-indexed array A consisting of N
integers returns 1
if there exists a triple (P, Q, R) such that 0 < P < Q < R < N
.
A[P] + A[Q] > A[R],
A[Q] + A[R] > A[P],
A[R] + A[P] > A[Q].
The function should return 0
if such triple does not exist. Assume that 0 < N < 100,000
. Assume that each element of the array is an integer in range [-1,000,000..1,000,000]
.
For example, given array A
such that
A[0]=10, A[1]=2, A[2]=5, A[3]=1, A[4]=8, A[5]=20
the function should return 1
, because the triple (0, 2, 4)
fulfills all of the required conditions.
For array A
such that
A[0]=10, A[1]=50, A[2]=5, A[3]=1
the function should return 0
.
If I do a triple loop, this would be very very slow (complexity: O(n^3)
). I am thinking maybe to use to store an extra copy of the array and sort it, and use a binary search for a particular number. But I don't know how to break down this problem.
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
我有另一种解决方案来计算三角形。其时间复杂度为O(N**3),处理长数组需要很长时间。
I have got another solution to count triangles. Its time complexity is O(N**3) and takes long time to process long arrays.
PHP解决方案:
PHP Solution :
对我来说,反转 Vlad 解决方案的循环似乎更容易理解。
等式A[j-1]+A[j]> A[j+1]可以改变为A[k-2]+A[k-1]>A[k]。用文字解释,最后两个最大数字的总和应该大于当前检查的最大值(A[k])。如果最后两个最大的数(A[k-2]和A[k-1])相加的结果不大于A[k],我们可以进入循环的下一次迭代。
另外,我们可以添加 Vlad 提到的对负数的检查,并提前停止循环。
Reversing the loop from Vlad solution for me seems to be easier to understand.
The equation A[j-1] + A[j] > A[j+1] could be changed to A[k-2]+A[k-1]>A[k]. Explained in words, the sum of the last two largest numbers should be bigger than current largest value being checked (A[k]). If the result of adding the last two largest numbers(A[k-2] and A[k-1]) is not bigger than A[k], we can go to the next iteration of the loop.
In addition, we can add the check for negative numbers that Vlad mentioned, and stop the loop earlier.
这是我在 C# 中的解决方案,其正确性为 90%(测试
extreme_arith_overflow1 -overflow test, 3 MAXINTs-
返回错误答案)和 100% 性能。Here's my solution in C#, which gets 90% correctness (the wrong answer is returned for test
extreme_arith_overflow1 -overflow test, 3 MAXINTs-
) and 100% performance.上述实现在时间复杂度上是线性的。这个概念很简单,使用他们给出的公式提取一系列排序元素的三元组。
The above implementation is Linear in time complexity. The concept is simple use the formaula they gave extracting a series of triplets of sorted elements.
100% Swift 解决方案:
100% Swift solution:
在 ruby 中,
只需将其移植为您选择的语言即可
In ruby what about
Just port it in the language of your choice
在爪哇中:
In Java:
这是java中的简单解决方案,得分为100/100
Here's simple solution in java with 100/100 score
这是 Vlad 提出的算法的实现。现在的问题需要避免溢出,因此需要强制转换为
long long
。Here is an implementation of the algorithm proposed by Vlad. The question now requires to avoid overflows, therefore the casts to
long long
.首先进行快速排序,这通常需要 nlogn。
并且可以通过二分查找省略第三个循环,该循环可以取 log(n)。
总而言之,复杂度降低到n^2log(n)。
Do a quick sort first, this will generally take nlogn.
And you can omit the third loop by binary search, which can take log(n).
So altogether, the complexity is reduced to n^2log(n).
100/100 php 解决方案: http:// www.rationalplanet.com/php-lated/maxproductof Three-demo-task-at-codility-com.html
A 100/100 php solution: http://www.rationalplanet.com/php-related/maxproductofthree-demo-task-at-codility-com.html
Python:
排序:对数线性复杂度 O(N log N)
Python:
Sorting: Loglinear complexity O(N log N)
首先,您可以对顺序进行排序。对于排序序列,检查
A[i] + A[j] > 就足够了。 A[k]
对于i
j< k
,因为A[i] + A[k] > A[k]> A[j]
等,因此其他 2 个不等式自动成立。(从现在开始,
i < j < k
。)接下来,检查
A[i] + A[j] > 就足够了。 A[j+1]
,因为其他A[k]
更大(因此,如果不等式对于某些k
成立,那么对于k = j + 1 也是如此)。
接下来,检查
A[j-1] + A[j] > 就足够了。 A[j+1]
,因为其他A[i]
更小(因此,如果不等式对于某些i
成立,则对于i 也成立= j - 1 也是如此)。
因此,您只需进行线性检查:您需要检查是否至少有一个
j
A[j-1] + A[j] > A[j+1]
成立。总共
O(N log N) {排序} + O(N) {检查} = O(N log N)
。解决有关负数的评论:确实,这是我在原始解决方案中没有考虑到的。考虑负数不会对解决方案产生太大影响,因为没有负数可以成为三角形三元组的一部分。事实上,如果
A[i]
、A[j]
和A[k]
形成一个三角形三元组,则A[i ]+A[j]> A[k]
,A[i] + A[k]> A[j]
,这意味着2 * A[i] + A[j] + A[k] > A[k] + A[j]
,因此2 * A[i] > 0
,所以A[i]> 0
且对称性A[j] > 0,
A[k]> 0 。
这意味着我们可以安全地从序列中删除负数和零,这在排序后的 O(log n) 时间内完成。
First of all, you can sort your sequence. For the sorted sequence it's enough to check that
A[i] + A[j] > A[k]
fori < j < k
, becauseA[i] + A[k] > A[k] > A[j]
etc., so the other 2 inequalities are automatically true.(From now on,
i < j < k
.)Next, it's enough to check that
A[i] + A[j] > A[j+1]
, because otherA[k]
are even bigger (so if the inequality holds for somek
, it holds fork = j + 1
as well).Next, it's enough to check that
A[j-1] + A[j] > A[j+1]
, because otherA[i]
are even smaller (so if inequality holds for somei
, it holds fori = j - 1
as well).So, you have just a linear check: you need to check whether for at least one
j
A[j-1] + A[j] > A[j+1]
holds true.Altogether
O(N log N) {sorting} + O(N) {check} = O(N log N)
.Addressing the comment about negative numbers: indeed, this is what I didn't consider in the original solution. Considering the negative numbers doesn't change the solution much, since no negative number can be a part of triangle triple. Indeed, if
A[i]
,A[j]
andA[k]
form a triangle triple, thenA[i] + A[j] > A[k]
,A[i] + A[k] > A[j]
, which implies2 * A[i] + A[j] + A[k] > A[k] + A[j]
, hence2 * A[i] > 0
, soA[i] > 0
and by symmetryA[j] > 0
,A[k] > 0
.This means that we can safely remove negative numbers and zeroes from the sequence, which is done in
O(log n)
after sorting.