三角形:确定数组是否包含三角形三元组(Codility)

时间:2017-07-04 18:19:31

标签: c++ algorithm math integer-overflow

这是来自Codility的三角问题:

  

给出了由N个整数组成的零索引数组A.   如果0≤P<1,则三重态(P,Q,R)是三角形。 Q&lt; R&lt; N和:

     

A [P] + A [Q]&gt; A [R],
   A [Q] + A [R]> A [P],
   A [R] + A [P]> A [Q]。

     

写一个函数:

int solution(vector<int> &A);  
     

给定由N个整数组成的零索引数组A,返回1   如果此数组存在三角形三元组并返回0   除此以外。

     

例如,给定阵列A使得:
  A [0] = 10,A [1] = 2,A [2] = 5,A [3] = 1,A [4] = 8,A [5] = 20   三联(0,2,4)是三角形,函数应返回1.

     

给定阵列A使得:
  A [0] = 10,A [1] = 50,A [2] = 5,A [3] = 1   函数应返回0.

     

假设:

     

N是[0..100,000]范围内的整数;
   数组A的每个元素都是该范围内的整数    [-2,147,483,648..2,147,483,647]。

这是我在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;
}

我检查了那里的评论,所有解决方案与我的相似 然而,虽然其他人声称已经获得100%,但我只获得了93%的分数 我得到了所有的测试用例除了一个:

  

extreme_arith_overflow1
  溢出测试,3 MAXINTs

我认为这个案例有这样的输入:
[2147483647,2147483647,2147483647]

所以我将它添加到自定义测试用例中,当答案明显为1时,答案结果为0 我也试过[1900000000,1900000000,1900000000],答案仍然是0.
但是,[1000000000,1000000000,1000000000]是正确答案为1.

任何人都可以告诉我为什么会出现这种结果? 非常感谢。

17 个答案:

答案 0 :(得分: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;
    }

答案 1 :(得分:2)

这是我用Python编写的干净解决方案。我有100%的Codility。 这种逻辑可以适应任何其他编程语言。

注意::如果数组是 sorted ,则只需检查两个连续元素的和是否大于下一个元素(A [i] + A [i + 1]> A [i + 2]),因为在这种情况下,其他两个条件(A [i + 1] + A [i + 2]> A [i],A [i] + A [ i + 2]> A [i + 1])始终为真。

希望对您有帮助。

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

答案 2 :(得分:1)

这里有几个问题

  1. 三角形的边不能为0,因为它是一个长度。您必须添加该检查,否则您将失败。即不会得到100%。

  2. 由于您可以拥有所有INT_MAX或LONG_MAX的输入数组(请参阅Linux example),因此您需要将该总和存储为双倍或长整数。

  3. 您无需在此检查所有三个条件,即

    A [P] + A [Q]&gt; A [R], A [Q] + A [R]> A [P], A [R] + A [P]> A [Q]。

    如果您对数组进行了排序而不是

    A [Q] + A [R]> A [P]&amp;&amp;和 A [R] + A [P]> A [Q]

    总是正确的,因为0≤P<1。 Q&lt; R即R大于P和Q. 因此,您只应检查A[P] + A[Q] > A[R]

  4. 您已经检查了A.size()&lt; 3这样很好。 我在http://www.cplusplus.com/reference/climits/添加了一个C实现。 您可以将其与解决方案进行比较

答案 3 :(得分:1)

我的Java解决方案具有100/100,时间复杂度为O(N * log(N))

带有解释逻辑的注释

// 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;
}

基本上,当您检查整数的X + Y值(大于整数限制)时,代码将在溢出时失败。因此我们无需检查X + Y > Z,而只需检查等效语句X > Z - Y(不是简单的数学方法吗?)。另外,您也可以始终使用long,但这在解决方案存储方面会更糟。

还要确保您跳过负值,因为三角形不能有负边值。

欢呼

答案 4 :(得分:0)

简单的变化:首先,您观察到负整数不能是三角形三元组的一部分。这意味着您可以将所有整数转换为无符号整数,并且不再有任何溢出。

答案 5 :(得分:0)

排序现在不起作用,这是一个由 Codility 修复的错误。现在,我正在使用这段代码获得 93%

您可以在下面看到结果:

Codility test Results

<块引用>

0 <= P < Q < R < N

 public static int solution(int[] unfilteredArray) {
    int[] array = filterLessThanOneElements(unfilteredArray);

    for(int i = 0; i <= (array.length - 3) ; i++) {
        long p = array[i];
        for(int j = i+1; j <= (array.length - 2); j++) {
            long q = array[j];
            for(int k = j+1; k <= (array.length - 1); k++) {
                long r = array[k];
                if((p + q > r) && (q + r > p) && (r + p > q)) {
                    return 1;
                }
            }
        }
    }

    return 0;
}

// The mose efficient way to remove duplicates
// TIME COMPLEXITY : O(N)
private static int[] filterLessThanOneElements(int[] unfilteredArray) {
    int k = 0;
    for(int i = 0; i < unfilteredArray.length; i++) {
        if(unfilteredArray[i] > 0) {
            unfilteredArray[k++] = unfilteredArray[i];
        }
    }
    return Arrays.copyOfRange(unfilteredArray, 0, k);
}

答案 6 :(得分:0)

不过,这是 javascript 解决方案(TC:O(N*log(N)),以防万一你们想要:)。

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;
}

答案 7 :(得分:0)

我的C#解决方案得分为100。

const track1Subject$ = new Subject();
const track1$ = track1Subject$.asObservable();
const track2Subject$ = new Subject();
const track2$ = track2Subject$.asObservable();
const Observable1$ = timer(1000, 2000).pipe(
  map(() => 1),
  tap(console.log),
  tap(() => track1Subject$.next()),
  take(5)
);
const Observable2$ = timer(1700, 1700).pipe(
  map(() => 2),
  tap(console.log),
  tap(() => track2Subject$.next()),
  take(5)
);
const Observable3$ = combineLatest([track1$, track2$]).pipe(
  take(1),
  map(() => "Hello World!"),
  tap(console.log)
);
Observable1$.subscribe();
Observable2$.subscribe();
Observable3$.subscribe();

答案 8 :(得分:0)

我的Java解决方案100/100我们没有比较加法,而是比较了减法,因为我们可以有一个 Integer.MAX_VALUE ,我们将获取损坏的数据。

 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;
}

答案 9 :(得分:0)

诀窍是在数组上找到一个小于数组上其他两个数之和的数字,因此对数组进行排序然后搜索该数字即可解决该问题。强制转换,以至于有时总和的值会超过允许的整数

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;
    }

答案 10 :(得分:0)

Ruby 100%解决方案

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

答案 11 :(得分:0)

//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;
}

答案 12 :(得分:0)

工作100%,并在不同情况下进行了测试。

我认为解决方案未涵盖所有可能性 与结合 P,Q,R

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

索引组合

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

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

....

这些是解决此问题所需的组合。

//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;
    }

答案 13 :(得分:0)

我在这里使用了3个for循环(不对数组进行排序)来解决此问题。

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;
}

答案 14 :(得分:0)

或者您可以更改if子句,如下所示

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])

使用减法而不是加法。

答案 15 :(得分:0)

我用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))

答案 16 :(得分:-1)

这是因为integer overflow

试试这个:

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

编辑:使用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;