如何知道我们的数组中存在三角形三元组?

发布于 2024-10-25 08:57:02 字数 848 浏览 2 评论 0原文

我被困在解决以下面试练习问题中:
我必须编写一个函数:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

千里故人稀 2024-11-01 08:57:04

我有另一种解决方案来计算三角形。其时间复杂度为O(N**3),处理长数组需要很长时间。

Private Function solution(A As Integer()) As Integer
    ' write your code in VB.NET 4.0
    Dim result, size, i, j, k As Integer
        size = A.Length
        Array.Sort(A)
        For i = 0 To Size - 3
            j = i + 1
            While j < size
                k = j + 1
                While k < size
                    If A(i) + A(j) > A(k) Then
                        result += 1
                    End If
                    k += 1
                End While
                j += 1
            End While
        Next
        Return result
End Function

I have got another solution to count triangles. Its time complexity is O(N**3) and takes long time to process long arrays.

Private Function solution(A As Integer()) As Integer
    ' write your code in VB.NET 4.0
    Dim result, size, i, j, k As Integer
        size = A.Length
        Array.Sort(A)
        For i = 0 To Size - 3
            j = i + 1
            While j < size
                k = j + 1
                While k < size
                    If A(i) + A(j) > A(k) Then
                        result += 1
                    End If
                    k += 1
                End While
                j += 1
            End While
        Next
        Return result
End Function
苍暮颜 2024-11-01 08:57:04

PHP解决方案:

function solution($x){
    sort($x);
    if (count($x) < 3) return 0; 
    for($i = 2; $i < count($x); $i++){
        if($x[$i] < $x[$i-1] + $x[$i-2]){
            return 1;
        }
    }

    return 0;
}

PHP Solution :

function solution($x){
    sort($x);
    if (count($x) < 3) return 0; 
    for($i = 2; $i < count($x); $i++){
        if($x[$i] < $x[$i-1] + $x[$i-2]){
            return 1;
        }
    }

    return 0;
}
江湖正好 2024-11-01 08:57:04

对我来说,反转 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 提到的对负数的检查,并提前停止循环。

int solution(vector<int> &A) {
    sort(A.begin(),A.end());
    for (int k = A.size()-1; k >= 2 && A[k-2] > 0 ; --k) {
        if ( A[k-2]+A[k-1] > A[k] )
            return 1;
    }
    return 0;
}

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.

int solution(vector<int> &A) {
    sort(A.begin(),A.end());
    for (int k = A.size()-1; k >= 2 && A[k-2] > 0 ; --k) {
        if ( A[k-2]+A[k-1] > A[k] )
            return 1;
    }
    return 0;
}
难理解 2024-11-01 08:57:04

这是我在 C# 中的解决方案,其正确性为 90%(测试 extreme_arith_overflow1 -overflow test, 3 MAXINTs- 返回错误答案)和 100% 性能。

private struct Pair
{
    public int Value;
    public int OriginalIndex;
}

private static bool IsTriplet(Pair a, Pair b, Pair c)
{
    if (a.OriginalIndex < b.OriginalIndex && b.OriginalIndex < c.OriginalIndex)
    {
        return ((long)(a.Value + b.Value) > c.Value
                && (long)(b.Value + c.Value) > a.Value
                && (long)(c.Value + a.Value) > b.Value);
    }
    else if (b.OriginalIndex < c.OriginalIndex && c.OriginalIndex < a.OriginalIndex)
    {
        return ((long)(b.Value + c.Value) > a.Value
                    &&(long)(c.Value + a.Value) > b.Value
                    && (long)(a.Value + b.Value) > c.Value);
    }
    // c.OriginalIndex < a.OriginalIndex && a.OriginalIndex < b.OriginalIndex
    return ((long)(c.Value + a.Value) > b.Value
                && (long)(a.Value + b.Value) > c.Value
                && (long)(b.Value + c.Value) > a.Value);
}

public static int Triplets(int[] A)
{
    const int IS_TRIPLET = 1;
    const int IS_NOT_TRIPLET = 0;

    Pair[] copy = new Pair[A.Length];

    // O (N)
    for (var i = 0; i < copy.Length; i++)
    {
        copy[i].Value = A[i];
        copy[i].OriginalIndex = i;
    }

    // O (N log N)
    Array.Sort(copy, (a, b) => a.Value > b.Value ? 1 : (a.Value == b.Value) ? 0 : -1);

    // O (N)
    for (var i = 0; i < copy.Length - 2; i++)
    {
        if (IsTriplet(copy[i], copy[i + 1], copy[i + 2]))
        {
            return IS_TRIPLET;
        }
    }

    return IS_NOT_TRIPLET;
}

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.

private struct Pair
{
    public int Value;
    public int OriginalIndex;
}

private static bool IsTriplet(Pair a, Pair b, Pair c)
{
    if (a.OriginalIndex < b.OriginalIndex && b.OriginalIndex < c.OriginalIndex)
    {
        return ((long)(a.Value + b.Value) > c.Value
                && (long)(b.Value + c.Value) > a.Value
                && (long)(c.Value + a.Value) > b.Value);
    }
    else if (b.OriginalIndex < c.OriginalIndex && c.OriginalIndex < a.OriginalIndex)
    {
        return ((long)(b.Value + c.Value) > a.Value
                    &&(long)(c.Value + a.Value) > b.Value
                    && (long)(a.Value + b.Value) > c.Value);
    }
    // c.OriginalIndex < a.OriginalIndex && a.OriginalIndex < b.OriginalIndex
    return ((long)(c.Value + a.Value) > b.Value
                && (long)(a.Value + b.Value) > c.Value
                && (long)(b.Value + c.Value) > a.Value);
}

public static int Triplets(int[] A)
{
    const int IS_TRIPLET = 1;
    const int IS_NOT_TRIPLET = 0;

    Pair[] copy = new Pair[A.Length];

    // O (N)
    for (var i = 0; i < copy.Length; i++)
    {
        copy[i].Value = A[i];
        copy[i].OriginalIndex = i;
    }

    // O (N log N)
    Array.Sort(copy, (a, b) => a.Value > b.Value ? 1 : (a.Value == b.Value) ? 0 : -1);

    // O (N)
    for (var i = 0; i < copy.Length - 2; i++)
    {
        if (IsTriplet(copy[i], copy[i + 1], copy[i + 2]))
        {
            return IS_TRIPLET;
        }
    }

    return IS_NOT_TRIPLET;
}
一枫情书 2024-11-01 08:57:04
public static int solution(int[] A) {
    // write your code in Java SE 8
    long p, q, r;
    int isTriangle = 0;

    Arrays.sort(A);
    for (int i = 0; i < A.length; i += 1) {

        if (i + 2 < A.length) {
            p = A[i];
            q = A[i + 1];
            r = A[i + 2];
            if (p >= 0) {
                if (Math.abs(p) + Math.abs(q) > Math.abs(r) && Math.abs(q) + Math.abs(r) > Math.abs(p) && Math.abs(r) + Math.abs(p) > Math.abs(q))
                    return 1;
            }
        } else return 0;


    }

    return isTriangle;

}

上述实现在时间复杂度上是线性的。这个概念很简单,使用他们给出的公式提取一系列排序元素的三元组。

public static int solution(int[] A) {
    // write your code in Java SE 8
    long p, q, r;
    int isTriangle = 0;

    Arrays.sort(A);
    for (int i = 0; i < A.length; i += 1) {

        if (i + 2 < A.length) {
            p = A[i];
            q = A[i + 1];
            r = A[i + 2];
            if (p >= 0) {
                if (Math.abs(p) + Math.abs(q) > Math.abs(r) && Math.abs(q) + Math.abs(r) > Math.abs(p) && Math.abs(r) + Math.abs(p) > Math.abs(q))
                    return 1;
            }
        } else return 0;


    }

    return isTriangle;

}

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.

美羊羊 2024-11-01 08:57:04

100% Swift 解决方案:

public func solution(_ A : inout [Int]) -> Int {
    guard A.count > 2 else { return 0 }
    A.sort()

    for i in 2..<A.count {
        if A[i - 2] + A[i - 1] > A[i] {
            return 1
        }
    }
    return 0
}

100% Swift solution:

public func solution(_ A : inout [Int]) -> Int {
    guard A.count > 2 else { return 0 }
    A.sort()

    for i in 2..<A.count {
        if A[i - 2] + A[i - 1] > A[i] {
            return 1
        }
    }
    return 0
}
李白 2024-11-01 08:57:04

在 ruby​​ 中,

def check_triangle (_array)
  for p in 0 .. _array.length-1
    for q in p .. _array.length-1
      for r in q .. _array.length-1
        return true if _array[p] + _array[q] > _array[r] && _array[p] + _array[r] > _array[q] && _array[r] + _array[q] > _array[p]
      end
    end
  end

  return false
end

只需将其移植为您选择的语言即可

In ruby what about

def check_triangle (_array)
  for p in 0 .. _array.length-1
    for q in p .. _array.length-1
      for r in q .. _array.length-1
        return true if _array[p] + _array[q] > _array[r] && _array[p] + _array[r] > _array[q] && _array[r] + _array[q] > _array[p]
      end
    end
  end

  return false
end

Just port it in the language of your choice

携余温的黄昏 2024-11-01 08:57:03

在爪哇中:

public int triangle2(int[] A) {

    if (null == A)
        return 0;
    if (A.length < 3)
        return 0;

    Arrays.sort(A);

    for (int i = 0; i < A.length - 2 && A[i] > 0; i++) {
        if (A[i] + A[i + 1] > A[i + 2])
            return 1;
    }

    return 0;

}

In Java:

public int triangle2(int[] A) {

    if (null == A)
        return 0;
    if (A.length < 3)
        return 0;

    Arrays.sort(A);

    for (int i = 0; i < A.length - 2 && A[i] > 0; i++) {
        if (A[i] + A[i + 1] > A[i + 2])
            return 1;
    }

    return 0;

}
固执像三岁 2024-11-01 08:57:03

这是java中的简单解决方案,得分为100/100

class Solution {
  public int solution(int[] A) {
    // write your code in Java SE 8
    Arrays.sort(A);
    for (int i = 0; i < A.length - 2; ++i) {
      long a = A[i] + (long) A[i + 1];
      long b = A[i + 2];
      if (a > b) {
        return 1;
      }
    }
    return 0;
  }
}

Here's simple solution in java with 100/100 score

class Solution {
  public int solution(int[] A) {
    // write your code in Java SE 8
    Arrays.sort(A);
    for (int i = 0; i < A.length - 2; ++i) {
      long a = A[i] + (long) A[i + 1];
      long b = A[i + 2];
      if (a > b) {
        return 1;
      }
    }
    return 0;
  }
}
塔塔猫 2024-11-01 08:57:03

这是 Vlad 提出的算法的实现。现在的问题需要避免溢出,因此需要强制转换为long long

#include <algorithm>
#include <vector>

int solution(vector<int>& A) {

    if (A.size() < 3u) return 0;

    sort(A.begin(), A.end());

    for (size_t i = 2; i < A.size(); i++) {
        const long long sum = (long long) A[i - 2] + (long long) A[i - 1];
        if (sum > A[i]) return 1;
    }

    return 0;

}

Here is an implementation of the algorithm proposed by Vlad. The question now requires to avoid overflows, therefore the casts to long long.

#include <algorithm>
#include <vector>

int solution(vector<int>& A) {

    if (A.size() < 3u) return 0;

    sort(A.begin(), A.end());

    for (size_t i = 2; i < A.size(); i++) {
        const long long sum = (long long) A[i - 2] + (long long) A[i - 1];
        if (sum > A[i]) return 1;
    }

    return 0;

}
泪痕残 2024-11-01 08:57:03

首先进行快速排序,这通常需要 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).

偏爱自由 2024-11-01 08:57:03

100/100 php 解决方案: http:// www.rationalplanet.com/php-lated/maxproductof Three-demo-task-at-codility-com.html

function solution($A) {
    $cnt = count($A);
    sort($A, SORT_NUMERIC);
    return max($A[0]*$A[1]*$A[$cnt-1], $A[$cnt-1]*$A[$cnt-2]*$A[$cnt-3]);
}

A 100/100 php solution: http://www.rationalplanet.com/php-related/maxproductofthree-demo-task-at-codility-com.html

function solution($A) {
    $cnt = count($A);
    sort($A, SORT_NUMERIC);
    return max($A[0]*$A[1]*$A[$cnt-1], $A[$cnt-1]*$A[$cnt-2]*$A[$cnt-3]);
}
这样的小城市 2024-11-01 08:57:03

Python:

def solution(A):
    A.sort()
    for i in range(0,len(A)-2):
        if A[i]+A[i+1]>A[i+2]:
            return 1
    return 0

排序:对数线性复杂度 O(N log N)

Python:

def solution(A):
    A.sort()
    for i in range(0,len(A)-2):
        if A[i]+A[i+1]>A[i+2]:
            return 1
    return 0

Sorting: Loglinear complexity O(N log N)

疯了 2024-11-01 08:57:02

首先,您可以对顺序进行排序。对于排序序列,检查 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] for i < j < k, because A[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 other A[k] are even bigger (so if the inequality holds for some k, it holds for k = j + 1 as well).

Next, it's enough to check that A[j-1] + A[j] > A[j+1], because other A[i] are even smaller (so if inequality holds for some i, it holds for i = 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] and A[k] form a triangle triple, then A[i] + A[j] > A[k], A[i] + A[k] > A[j], which implies 2 * A[i] + A[j] + A[k] > A[k] + A[j], hence 2 * A[i] > 0, so A[i] > 0 and by symmetry A[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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文