Triangle : Determine whether a triangle can be built from a given set of edges

匿名 (未验证) 提交于 2019-12-03 01:05:01

问题:

I have found a solution on the net for the codility problem below :

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

For example, consider 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.

Write a function:

 int solution(int A[], int N); 

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.

The solution is like this :

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

But when we sort the array, the original index are no more valid and item in i position can move to j position with j>i or j

The solutin suppose that values that verify assertion (Triangle) is automaticly adjacent in sorted array.

In example array, if we change like this :

A[0] = 10 A[1] = 6 (replace 2) A[2] = 5 A[3] = 1 A[4] = 8 A[5] = 20 Here we get 2 new traingle 10 6 5 and 6 5 8. (and 10 5 8)

We sort : 1 5 6 8 10 20 --> Here, original solution (10,5,8) values are not adjacent (no traingle) but instead we have (5,6,8) and (6 8 10). Then algorithm return 1. It seem that if triangle exist then at least values of one triangle will be adjacent but I doesn't find any proof.

回答1:

Let A denote the original array and let B denote the sorted array (to avoid confusion)

Let p, q, r be such that they form a triangle. Assume that 0 <= A[p] <= A[q] <= A[r].

Let i be such that B[i+1] = A[q]. Let j be such that B[j] = A[p] and k be such that B[k] = A[r]. Then by definition B[j] + B[i+1] > B[k]. Because B is sorted and j < (i+1) < k we have B[i] + B[i+1] >= B[j] + B[i+1] > B[k] >=B[i+2]. It follows that if you do have a triangle, the algorithm returns true.



回答2:

It's pretty simple really, and I believe vib to be right but I'll try to put it in a simpler way.

Let us suppose you have three elements that are triangular with values u, v, w, then they have (at least) one maximum value. Let us consider that to be w, so u <= w and v <= w

  • The definition of "triangular" is equivalent to u + v > w, because if this is true then any sum containing w will always be greater than the other individual values *
  • If you keep track of the new position of w when reordering, you can see that the two elements just before it can be
    • either u and v, so you keep the same triangle,
    • or they can be replaced with other values u' and v', which are greater or equal to u and v but smaller than w, and then u' + v' >= u + v > w, so by our new definition of triangular we have another triangle.

So the existence of a triangle in the array proves that there exists at least one adjacent triangle in the sorted array, which does not have to be the same.


* It's completely trivial for positive numbers since w is the max. Here's a general demonstration that does not suppose only positive integers. Our hypothesis are v <= w, u <= w and u + v > w. Let us prove by contradiction that u + w <= v it is impossible.

Supposing u + w <= v, we get by adding v on both sides, u + v + w <= v + v, and since u + v is strictly superior to w by hypothesis, we have w + w < u + v + w <= v + v thus w < v, which is contradicting our hypothesis.



回答3:

Below is a solution for the Codility Triangle problem in C++.

#include <algorithm>  bool isTriangular(int p2, int q2, int r2) {     long p, q, r;      p = (long)p2;     q = (long)q2;     r = (long)r2;      if (p + q > r &&         q + r > p &&         r + p > q) {         return true;     }     return false; }  int solution(vector<int> &A) {      int size = A.size();     if (size < 3) {         return 0;     }      vector<int>&S(A);     sort(S.begin(), S.end());      int q = size/2;     int p = q-1;     int r = q+1;      if (isTriangular(S[p],S[q],S[r])) {         return 1;     }      while (true) {                 if (p == 0 && r == size-1) {             break;         }          if (p != 0) {             --p;              if (isTriangular(S[p],S[q],S[r])) {                 return 1;             }         }          if (r != size-1) {             ++r;              if (isTriangular(S[p],S[q],S[r])) {                 return 1;             }         }     }      return 0; } 


回答4:

My solution in Java was this. It works and solves the problem, but when tested on Codility I got 0%, perhaps because of time complexity. Any ideas on how to improve welcome in the comments, I can edit the answer for all to see:

import java.util.Arrays;  public class Triangular {     public static int solution(int[] A) {         // Sort the array and nullify values which won't count.          Arrays.sort(A);         for(int i=0;i<A.length;i++){             if(A[i]>A.length){                 A[i]=0;             }         }          //Increment the counter, if a triangle exists then this works.         int count = 1;         for(int i=1;i<A.length-1;i++){             if(A[i-1]+A[i+1]>A[i]){                 count++;             }         }          switch(count){             case 3:                 return 1;             default:                 return 0;         }      } 


回答5:

I got %93 for my first try ,it had overflow exception and failed in one test case. then I needed to first convert the values into long then do the mathematical calculation. below is the code.

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


回答6:

Here is a c++ solution that gives 93% one test fails because it uses out of bound numbers , you need to convert numbers to long to get 100%. I'm lazy and happy with 93 :)

#include <algorithm> #include <vector> using namespace std; int solution(vector<int> &A) {     if(A.size() < 3){         return 0;     }     sort(A.begin(), A.end());     for(unsigned int i = 0 ; i < A.size() - 2 ; i++){         if(A[i] + A[i+1] > A[i+2] && A[i] + A[i+2] > A[i+1]){             return 1;         }     }     return 0; } 


回答7:

Here is my solution in Java. Gives me 100% result on Codility.

class Solution {     public int solution(int[] A) {         Arrays.sort(A);          for (int i = 2; i < A.length; i++) {             long p = A[i - 2];              long q = A[i - 1];              long r = A[i];              if (p + q <= r) {                 continue;             }              if (r + p <= q) {                 continue;             }              if (q + r <= p) {                 continue;             }              return 1;         }          return 0;     } } 


回答8:

My solution gives 100%.

Other solutions have more tests than it is necessary, because after sorting the array A[Q] + A[R] > A[P] AND A[R] + A[P] > A[Q] is always true, so we don't need to test it: A[R] is greater than A[Q] and A[P].

And the problem of overflow can be avoided using A[P] > A[R] - A[Q] instead of A[P] + A[Q] > A[R].

import java.util.*;  class Solution {     public int solution(int[] A) {         if (A.length < 3) {             return 0;         }         Arrays.sort(A);         for (int i = 2; i < A.length; ++i) {             if (A[i - 2] > A[i] - A[i - 1]) {               return 1;                     }         }         return 0;     } } 


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