Triangle: Determine if an array includes a triangular triplet (Codility)

筅森魡賤 提交于 2021-02-08 21:16:25

问题


This is the Triangle problem from Codility:

A zero-indexed array A consisting of N integers is given.
A triplet (P, Q, R) is triangular if 0 ≤ P < Q < R < N and:

A[P] + A[Q] > A[R],
A[Q] + A[R] > A[P],
A[R] + A[P] > A[Q].

Write a function:

int solution(vector<int> &A);  

that, given a zero-indexed array A consisting of N integers, returns 1 if there exists a triangular triplet for this array and returns 0 otherwise.

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 Triplet (0, 2, 4) is triangular, the function should return 1.

Given array A such that:
A[0] = 10, A[1] = 50, A[2] = 5, A[3] = 1
function should return 0.

Assume that:

N is an integer within the range [0..100,000];
each element of array A is an integer within the range [−2,147,483,648..2,147,483,647].

And here is my solution in C++:

int solution(vector<int> &A) {
    if(A.size()<3) return 0;

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

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

I've checked the comments there and all the solutions seems similar to mine.
However, while others claimed to have gotten 100%, I only got a 93% score.
I got all the tests cases correct EXCEPT for one:

extreme_arith_overflow1
overflow test, 3 MAXINTs

I assume this case has some input like this:
[2147483647, 2147483647, 2147483647]

So I add this to the custom test case, and the answer turns out to be 0 when it clearly should be 1.
I also tried [1900000000, 1900000000, 1900000000], and the answer is still 0.
However, [1000000000, 1000000000, 1000000000] is correct with answer of 1.

Can anyone clue me in on why this result occured?
Greatly appreciated.


回答1:


My solution in Java with 100/100 and time complexity of O(N*log(N))

With comments explaining the logic

// you can also use imports, for example:
// import java.util.*;

// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");
import java.util.Arrays;

class Solution {

    public int solution(int[] A) {

    int N = A.length;
    if (N < 3) return 0;
    Arrays.sort(A);

    for (int i = 0; i < N - 2; i++) {

        /**
         * Since the array is sorted A[i + 2] is always greater or equal to previous values
         * So A[i + 2] + A[i] > A[i + 1] ALWAYS
         * As well ass A[i + 2] + A[i + 1] > A[i] ALWAYS
         * Therefore no need to check those. We only need to check if A[i] + A[i + 1] > A[i + 2]?
         * Since in case of A[i] + A[i + 1] > MAXINT the code would strike an overflow (ie the result will be greater than allowed integer limit)
         * We'll modify the formula to an equivalent A[i] > A[i + 2] - A[i + 1]
         * And inspect it there
         */
        if (A[i] >= 0 && A[i] > A[i + 2] - A[i + 1]) {

            return 1;
        }
    }

    return 0;
}

Basically when you check X + Y value of integers, that is greater than integer limit the code will fail on overflow. so instead of checking if X + Y > Z, we can simply check the equivalent statement if X > Z - Y (simple math isn't it?). Alternatively you could always use long but it will be a worse solution memory wise.

Also make sure you skip the negatives as a triangle cannot have a negative side value.

Cheers




回答2:


Java 100 %:

public int solution(int[] A){
        Arrays.sort(A);

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



回答3:


Here's my clean solution in Python. I got a 100% in Codility. This logic can be adapted to any other programming language.

Note: If the array is sorted, you only have to check that the sum of two consecutive elements is greater than the next element (A[i] + A[i+1] > A[i+2]), because in that case, the other two conditions (A[i+1]+A[i+2] > A[i], A[i]+A[i+2] > A[i+1]) will always be true.

I hope it helps.

def solution(A):

    #edge case check
    if len(A) < 3:
        return 0

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



回答4:


There are couple of issues here

  1. Side of a triangle can't be 0, since it is a length. You have to add that check or you'll fail that corner case. i.e. Wouldn't get 100%.

  2. Since you can have an input array of all INT_MAX or LONG_MAX (see http://www.cplusplus.com/reference/climits/), you need to store the sum in a double or long long.

  3. You don't have to check all three conditions here i.e.

    A[P] + A[Q] > A[R], A[Q] + A[R] > A[P], A[R] + A[P] > A[Q].

    If you have sorted the array than

    A[Q] + A[R] > A[P] &&
    A[R] + A[P] > A[Q]

    are always true because 0 ≤ P < Q < R i.e. R is greater than P and Q. So you should only check for A[P] + A[Q] > A[R].

You have already placed a check for A.size() < 3 so that is good. I have added a C implementation at https://github.com/naveedrasheed/Codility-Solutions/blob/master/Lesson6_Sorting/triangle.c. You can compare it with solution.




回答5:


I have used 3 for loop here( without sorting the array) to solve this problem.

public static int solution(int[] A) {

    for (int p = 0; p < A.length; p++) {
        for (int q = p + 1; q < A.length; q++) {
            for (int r = q + 1; r < A.length; r++) {

                if ((A[p] + A[q] > A[r]) && (A[q] + A[r] > A[p]) && (A[r] + A[p] > A[q])) {
                    System.out.println(A[p] + "  " + A[q] + " " + A[r]);
                    return 1;
                }
            }
        }
    }
    return 0;
}



回答6:


the trick is to find a number on the array that is less the sum of the other two on the array so sorting the array then searching for that number will solve it. casting to long that on sometimes the value of summation wil exceed the allowed integer

public int solution(int[] A) {
       int n = A.length;
       if(n<3){
           return 0;
       }
       Arrays.sort(A);
       for(int i=2; i<n; i++){
           if(A[i]<(long)A[i-1]+(long)A[i-2])
           return 1;
       }
       return 0;
    }



回答7:


My solution to this problem, written in Swift.

public func Triangle(_ A : inout [Int]) -> Int {

    A.sort()

    for i in 1..<A.count-1 {
        if(A[i] + A[i-1] > A[i+1]) {
            print("Triangle has edges: \(A[i-1]), \(A[i]), \(A[i+1])")
            return 1
        }
    }
    return 0
}

A = [10,2,5,1,8,20]
print("Triangle: ", Triangle(&A))



回答8:


Or you can change the if clause, like below

if(A[i]>A[i+2]-A[i+1] && A[i+1]>A[i]-A[i+2] && A[i+2]>A[i+1]-A[i])

using subtraction instead of addition.




回答9:


Works 100%, tested with different scenario's.

I think all the possibilities are not covered above solution Combination with P,Q,R

A[0] = 10, A[1] = 2, A[2] = 5, A[3] = 1, A[4] = 8, A[5] = 20

index combination

0+1>2, 1+2>0, 2+0>1

1+2>3, 2+3>1, 3+1>2

....

These are combinations needed to achieve this problem.

//Triangle
    /**
     * A[P] + A[Q] > A[R],
       A[Q] + A[R] > A[P],
       A[R] + A[P] > A[Q]
     */
    public int triangleSolution(int[] A) {
    int status = 0;
    for(int i=0; i<A.length; i++) {
        int[] B = removeTheElement(A, i);
        for(int j=0; j<B.length; j++) {
            int[] C = removeTheElement(B, j);
            for(int k=0; k<C.length; k++) {
                if((A[i] + B[j] > C[k]) &&
                   (B[j] + C[k] > A[i]) &&
                   (C[k] + A[i] > B[j])) {
                    return 1;
                }
            }
        }
    }
    return status;
}

    // Function to remove the element 
    public int[] removeTheElement(int[] arr, int index) 
    { 
        // Create another array of size one less 
        int[] anotherArray = new int[arr.length - 1]; 

        // Copy the elements except the index 
        // from original array to the other array 
        for (int i = 0, k = 0; i < arr.length; i++) { 

            // if the index is 
            // the removal element index 
            if (i == index) { 
                continue; 
            } 

            // if the index is not 
            // the removal element index 
            anotherArray[k++] = arr[i]; 
        } 

        //Java >8
        //IntStream.range(0, arr.length).filter(i -> i != index).map(i -> arr[i]).toArray();

        return anotherArray;
    }



回答10:


//My solution in C++ it avoid overflow

inline int Triangle(vector<int> &A) {

    if(A.size() < 3) return 0;
    sort(A.begin(), A.end());
    for(int i = 0; i < (int)A.size() - 2; ++i){
        int P = A[i], Q = A[i + 1], R =A[i + 2];
        if(( R - P - Q < 0) && ( P - Q - R < 0) && (Q - R - P < 0))
           return 1;
    }
    return 0;
}



回答11:


Ruby 100% solution

def solution(a)
  arr = a.select{|x| x >=0 }.sort
  arr.each_with_index do |p, pi|
    arr[(pi+1)..-1].each_with_index do |q, qi|
      arr[(qi+pi+2)..-1].each do |r|
        break if p+q <=r
        break if p+r <=q
        break if r+q <=p
        return 1
      end
    end
  end
  0
end



回答12:


My java Solution 100/100 Instead of comparing the Addition we compare the subtraction as we can have an Integer.MAX_VALUE an we will be getting corrupted data.

 public static int solution(int[] A) {
    int isATriangle = 0;
    Arrays.sort(A);
    if (A.length >= 3) {
        for (int i = 0; i < A.length - 2; i++) {
            if (A[i] > A[i + 2] - A[i + 1]
                    && A[i + 2] > A[i] - A[i + 1]
                    && A[i + 2] > A[i + 1] - A[i])
                isATriangle = 1;
        }
    }
    return isATriangle;
}



回答13:


My solution in C# with 100 score.

    using System;
    
    class Solution {
        public int solution(int[] A) {
            // write your code in C# 6.0 with .NET 4.5 (Mono)
            if(A.Length) <3)
               return 0;

            Array.Sort(A);
            int p,q,r;
            for(int i=A.Length-1;i>1; i--){
                p = A[i];
                q = A[i-1];
                r = A[i-2];
                if(p+q>r && q+r > p && r+p > q)
                    return 1;
            }
            return 0;
        }
    }



回答14:


It's javascript solution(TC: O(N*log(N)) though, in case you guys want :).

function solution(A) {
    if(A.length<3) return 0;

    A.sort((a,b)=>b - a);

    for(let i = 0,j = i+1;j < A.length-1;j++){
        let p = A[j],q = A[j+1],r = A[i]

        if(r - p > q) i++;
        else if(r - p < q) return 1;
    }

    return 0;
}



回答15:


It's because of integer overflow.

Try out this one:

int a1 = 1900000000;
int a2 = 1900000000;
int sum = a1+a2;  // sum will be -494967296

Edit: Use long long int.

long long int sum01 = A[i] + A[i+1];
long long int sum12 = A[i+1] + A[i+2];
long lont int sum02 = A[i] + A[i+2];

if (sum01 > A[i+2] && sum12 > A[i] && sum02 > A[i+1])
    return 1;


来源:https://stackoverflow.com/questions/44912099/triangle-determine-if-an-array-includes-a-triangular-triplet-codility

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!