Triplet whose sum in range (1,2)

白昼怎懂夜的黑 提交于 2019-12-03 01:04:32

问题


Given n positive real numbers in an array, find whether there exists a triplet among this set such that, the sum of the triplet is in the range (1, 2). Do it in linear time and constant space.

  • the array is not ordered.
  • numbers are positive
  • numbers are real numbers

Any help would be greatly appreciated. Thanks.


回答1:


The trick is to figure out a way to categorize the possible solutions and come up with a linear-time constant-space solution for each.

Consider the three ranges X = (0,2/3), Y = [2/3,1], Z = (1,2). At most one value can come from Z (if two values came from Z, then the sum would exceed 1+1=2). Similarly, at least one value must come from X. Suppose there were 3 values a <= b <= c so that 1 <= a+b+c <= 2 . Then, consider what possible classes of solutions are feasible:

A) `a \in X, b \in X, C \in X` 
B) `a \in X, b \in X, C \in Y` 
C) `a \in X, b \in X, C \in Z` 
D) `a \in X, b \in Y, C \in Y` 
E) `a \in X, b \in Y, C \in Z` 

So how can we test each case?

Case A is incredibly easy to test: the sum is guaranteed to be below 2, so we just need to test the largest sum (largest 3 elements in X) exceeds 1.

Case C is incredibly easy to test: since the sum is guaranteed to be above 1, we only need to check if the sum is below 2. So in order to do that, we just need to test the smallest 2 values in X and the smallest value in Z

Cases D and E are similar to C (since the sum must be at least 4/3 > 1, choose the smallest possible values in each class).

Case B is the only tricky case. 0 < a+b < 4/3 and 2/3 <= c <= 1. To handle case B, we consider these intervals : X1 = (0, 1/2), X2 = [1/2 2/3), Y = [2/3, 1].

This results in following three valid cases :

B1. a in X1, b in X2, c in Y

B2. a in X1, b in X1, c in Y

B3. a in X2, b in X2, c in Y

Case B1 & B3 : Sum of three numbers is always greater than 1 so we take minimum values and check if it is smaller than 2 or not.

Case B2 : Sum of three numbers is always less than 2, so we take maximum sum and check if is greater than 1 or not.

So to summarize, the tests are:

  • |X| >= 3 and Xmax(1) + Xmax(2) + Xmax(3) >= 1
  • |X| >= 2, |Z| >= 1, and Xmin(1)+Xmin(2)+Zmin(1) <= 2
  • |X| >= 1, |Y| >= 2, and Xmin(1)+Ymin(1)+Ymin(2) <= 2
  • |X| >= 1, |Y| >= 1, |Z| >= 1, and Xmin(1)+Ymin(1)+Zmin(1) <= 2
  • |X| >= 2, |Y| >= 1, and Xmax(1) + Xmax(2) + Ymin(1) < 2
  • |X| >= 2, |Y| >= 1, and Xmin(1) + Xmin(2) + Ymax(1) > 1)

Each test can be performed in linear time and constant space (you only need to find Xmax(1), Xmax(2), Xmax(3), Xmin(1), Xmin(2), Ymin(1), Ymin(2), Ymax(1), Zmin(1), all of which can be found in one pass even if the data is not sorted)




回答2:


So, you have an array of double data types of length n. Intialize three variables a,b and c as first 3 values of array.Now,iterate from i = 3 to n and check the following: 1)Check if sum falls in (1, 2),if it does then return true. 2)If not, then check if sum is greater than 2,if so, then replace MAX(a,b,c) to current element arr[i]. 3)Otherwise sum must be less than 1 then replace MIN(a,b,c) to current element arr[i].And finally after coming out of loop check once again for last triplet if sum falls in (1,2) then return true,otherwise return false.

enter code here
double a=arr[0], b=arr[1], c=arr[2];
for(int i=3 ; i<n ; i++){
    // check if sum fall in (1, 2)
    if(a+b+c > 1 && a+b+c < 2){
        return 1;
    }
    // if not, then check is sum greater than 2
    // if so, then replece MAX(a,b,c) to new number
    else if(a+b+c > 2){
        if(a>b && a>c){
            a = arr[i];
        }
        else if(b>a && b>c){
            b = arr[i];
        }
        else if(c>a && c>b){
            c = arr[i];
        }
    }
    // else then sum must be less than 1
    // then replace MIN(a,b,c) to new number
    else{
        if(a<b && a<c){
            a = arr[i];
        }
        else if(b<a && b<c){
            b = arr[i];
        }
        else if(c<a && c<b){
            c = arr[i];
        }
    }
}
// check for last a, b, c  triplet
if(a+b+c > 1 && a+b+c < 2){
    return 1;
}
else{
    return 0;
}



回答3:


Building upon @Soul Ec ideas, this is the code I came up with. Works perfectly fine.

vector<double> x;
vector<double> y;
vector<double> z;

double d = (double)2/3;

for(i = 0 ; i < arr.size() ; i++){
    if(arr[i] >= 0 && arr[i] < d)       x.push_back(arr[i]);
    else if(arr[i] >= d && arr[i] <= 1) y.push_back(arr[i]);
    else                                z.push_back(arr[i]);
}

sort(x.begin(), x.end());
sort(y.begin(), y.end());
sort(z.begin(), z.end());

int xsz = x.size();
int ysz = y.size();
int zsz = z.size();

if(xsz >= 3 && x[xsz-1] + x[xsz-2] + x[xsz-3] >= 1.0) return 1;
if(xsz >= 2 && zsz >= 1 && x[0] + x[1] + z[0] <= 2.0) return 1;
if(xsz >= 1 && ysz >= 2 && x[0] + y[0] + y[1] <= (double)2.0) return 1;
if(xsz >= 1 && ysz >= 1 && zsz >= 1 && x[0] + y[0] + z[0] <= 2.0) return 1;
if(xsz >= 2 && ysz >= 1){
    if(x[xsz-1] + x[xsz-2] + y[0] < 2.0 && x[xsz-1] + x[xsz-2] + y[0] > 1.0) return 1;
    if(x[0] + x[1] + y[ysz-1] > 1.0 && x[0] + x[1] + y[ysz-1] < 2.0) return 1;
}



回答4:


Java code for the solution given by @soul Ec.

we need to modify the case B. let say our numbers are a+b+c

there are three ranges 
    x1        x2           y  
 (0,1/2)   (1/2,2/3)    (2/3,1) 
we have 4 possibilities
1.   x1 + x1 +y
2.   x2 + x2 +y
3.   x1 + x2 +y
4    x2 + x1 +y

here case 3 and 4 are identical as sum of it will be same. so we have 3 cases only.

1.  x1 + x1 + y it is always <2         ( do x1max+x1max+ymax <2 to verify)
so we have to check if x1max(1)+x1max(2)+ymax(1) > 1
2. x2 + x2 + y it is always >1          ( do x2min+x2min+ymin >1 to verify)
so we have to check if x2min(1)+x2min(2)+ymin(1) <=2
3. x1 + x2 + y it is always >1           (do x1min+x2min+ymin >1 to verify)
so we have to check if x1min(1)+x2min(1)+ymin(1)<=2 
   public static int solve(ArrayList<String> A) {

      double d[]= new double[A.size()];
      for(int i=0;i<A.size();i++) {
          d[i]= Double.parseDouble(A.get(i));
      }


       double range1 = 0;
       double range2 = (double) 2/3;
       double range3 = 1;
       double range4 = 2;

       double range02 =(double) 1/2;

       // min and max in range (0,2/3)
       double min1= Double.MAX_VALUE;
       double min2=Double.MAX_VALUE;
       double min3=Double.MAX_VALUE;

       double max1= Double.MIN_VALUE;
       double max2=Double.MIN_VALUE;
       double max3=Double.MIN_VALUE;

       // min and max in range (2/3,1)
       double miny1= Double.MAX_VALUE;
       double miny2=Double.MAX_VALUE;
       double miny3=Double.MAX_VALUE;


       double maxy1= Double.MIN_VALUE;
       double maxy2=Double.MIN_VALUE;
       double maxy3=Double.MIN_VALUE;

       // min and max in range (1,2)
       double minz1= Double.MAX_VALUE;
       double minz2=Double.MAX_VALUE;
       double minz3=Double.MAX_VALUE;

       double maxz1= Double.MIN_VALUE;
       double maxz2=Double.MIN_VALUE;
       double maxz3=Double.MIN_VALUE;

        // min and max in range (0,1/2)
       double minxx1= Double.MAX_VALUE;
       double minxx2=Double.MAX_VALUE;
       double minxx3=Double.MAX_VALUE;

       double maxx1= Double.MIN_VALUE;
       double maxx2=Double.MIN_VALUE;
       double maxx3=Double.MIN_VALUE;

       // min and max in range (1/2,2/3)
       double minyy1= Double.MAX_VALUE;
       double minyy2=Double.MAX_VALUE;
       double minyy3=Double.MAX_VALUE;

       double maxyy1= Double.MIN_VALUE;
       double maxyy2=Double.MIN_VALUE;
       double maxyy3=Double.MIN_VALUE;




    for (int i = 0; i < d.length; i++) {
        if (d[i] >= range1 && d[i] < range02) {
            if (d[i] < minxx3) {
                minxx1=minxx2;
                minxx2=minxx3;
                minxx3 = d[i];


            } else if (d[i] > minxx3 && d[i] < minxx2) {
                minxx1=minxx2;
                minxx2 = d[i];

            } else if (d[i] > minxx3 && d[i] > minxx2 && d[i] < minxx1) {
                minxx1 = d[i];
            }

            if (d[i] > maxx3) {
                maxx1=maxx2;
                maxx2=maxx3;
                maxx3 = d[i];
            } else if (d[i] < maxx3 && d[i] > maxx2) {
                maxx1=maxx2;
                maxx2 = d[i];
            } else if (d[i] < maxx3 && d[i] < maxx2 && d[i] > maxx1) {
                maxx1 = d[i];
            }


        }

        if (d[i] >= range02 && d[i] < range2) {
            if (d[i] < minyy3) {
                minyy1=minyy2;
                minyy2=minyy3;
                minyy3 = d[i];


            } else if (d[i] > minyy3 && d[i] < minyy2) {
                minyy1=minyy2;
                minyy2 = d[i];

            } else if (d[i] > minyy3 && d[i] > minyy2 && d[i] < minyy1) {
                minyy1 = d[i];
            }

            if (d[i] > maxyy3) {
                maxyy1=maxyy2;
                maxyy2=maxyy3;
                maxyy3 = d[i];
            } else if (d[i] < maxyy3 && d[i] > maxyy2) {
                maxyy1=maxyy2;
                maxyy2 = d[i];
            } else if (d[i] < maxyy3 && d[i] < maxyy2 && d[i] > maxyy1) {
                maxyy1 = d[i];
            }


        }


        if (d[i] >= range1 && d[i] < range2) {
            if (d[i] < min3) {
                min1=min2;
                min2=min3;
                min3 = d[i];


            } else if (d[i] > min3 && d[i] < min2) {
                min1=min2;
                min2 = d[i];

            } else if (d[i] > min3 && d[i] > min2 && d[i] < min1) {
                min1 = d[i];
            }

            if (d[i] > max3) {
                max1=max2;
                max2=max3;
                max3 = d[i];
            } else if (d[i] < max3 && d[i] > max2) {
                max1=max2;
                max2 = d[i];
            } else if (d[i] < max3 && d[i] < max2 && d[i] > max1) {
                max1 = d[i];
            }


        }

        if (d[i] >= range2 && d[i] < range3) {
            if (d[i] < miny3) {
                miny1=miny2;
                miny2=miny3;
                miny3 = d[i];


            } else if (d[i] > miny3 && d[i] < miny2) {
                miny1=miny2;
                miny2 = d[i];

            } else if (d[i] > miny3 && d[i] > miny2 && d[i] < miny1) {
                miny1 = d[i];
            }

            if (d[i] > maxy3) {
                maxy1=maxy2;
                maxy2=maxy3;
                maxy3 = d[i];
            } else if (d[i] < maxy3 && d[i] > maxy2) {
                maxy1=maxy2;
                maxy2 = d[i];
            } else if (d[i] < maxy3 && d[i] < maxy2 && d[i] > maxy1) {
                maxy1 = d[i];
            }


        }


        if (d[i] >= range3 && d[i] <= range4) {
            if (d[i] < minz3) {
                minz1=minz2;
                minz2=minz3;
                minz3 = d[i];


            } else if (d[i] > minz3 && d[i] < minz2) {
                minz1=minz2;
                minz2 = d[i];

            } else if (d[i] > minz3 && d[i] > minz2 && d[i] < minz1) {
                minz1 = d[i];
            }

            if (d[i] > maxz3) {
                maxz1=maxz2;
                maxz2=maxz3;
                maxz3 = d[i];
            } else if (d[i] < maxz3 && d[i] > maxz2) {
                maxz1=maxz2;
                maxz2 = d[i];
            } else if (d[i] < maxz3 && d[i] < maxz2 && d[i] > maxz1) {
                maxz1 = d[i];
            }


        }




       }

    if(max1+max2+max3>=1 && max1!=Double.MIN_VALUE && max2!=Double.MIN_VALUE && max3!=Double.MIN_VALUE) 
        return 1;

    if(min3+min2+minz3<=2 && min3!=Double.MAX_VALUE && min2!=Double.MAX_VALUE && minz3!=Double.MAX_VALUE ) 
        return 1;

    if(min3+miny3+miny2<=2 && min3!=Double.MAX_VALUE && miny3!=Double.MAX_VALUE && miny2!=Double.MAX_VALUE)
       return 1;
    if(min3+miny3+minz3<=2 && min3!=Double.MAX_VALUE && miny3!=Double.MAX_VALUE && minz3!=Double.MAX_VALUE)
        return 1;

    if(maxx3+maxx2+maxy3>1 && maxx3!=Double.MIN_VALUE && maxx2!=Double.MIN_VALUE && maxy3!=Double.MIN_VALUE) {
        return 1;

    }

    if(minyy3+minyy2+miny3<=2 && minyy3!=Double.MAX_VALUE && minyy2!=Double.MAX_VALUE && miny3!=Double.MAX_VALUE) {
        return 1;
    }
    if(minxx3+minyy3+miny3<=2 && minxx3!=Double.MAX_VALUE && minyy3!=Double.MAX_VALUE && miny3!=Double.MAX_VALUE) {
        return 1;
    }




    return 0;






    }



回答5:


the solution is in c++(interviewbbit solution)

int Solution::solve(vector<string> &arr) {
int n=arr.size(),i;
vector<float>v;
for(i=0;i<n;i++)
{
    v.push_back(stof(arr[i]));
}
float a=v[0],b=v[1],c=v[2];

float mx=0;
for(i=3;i<n;i++)
{
    if(a+b+c<2 && a+b+c>1)
        return 1;
    else if(a+b+c>2)
    {
        if(a>b && a>c)
            a=v[i];
        else if(b>a && b>c)
            b=v[i];
        else
            c=v[i];
    }
    else
    {
        if(a<b && a<c)
            a=v[i];
        else if(b<a && b<c)
            b=v[i];
        else
            c=v[i];

    }
}
if(a+b+c>1 && a+b+c<2)
    return 1;
else
    return 0;
}



回答6:


We can easily do it in O(n) , we just need to find three minimum positive real numbers ,which we can find in one iteration and in the end if their summation lies in between (1,2) then return 1 else return 0.




回答7:


The problem in its whole as stated is undecidable. This is due to the fact that for any two real numbers a and b it cannot be decided if a > b holds (also see this answer of me). But you have to do at least one comparison of a real number against an integer value to solve that problem. Comparing against an integer doesn't make the problem easier since you could have a real number which is 2,00...001 where there is an arbitrary number of zeros between the digits 2 and 1 which you don't know beforehand. Storing such real numbers (probably not every one, but many of them) in the main memory of a computer is not a big problem for such specific ones, since they can be represented by an approximation algorithm.

for further information I suggest reading Complexity Theory of Real Functions



来源:https://stackoverflow.com/questions/19557505/triplet-whose-sum-in-range-1-2

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