web-dev-qa-db-fra.com

Triplet dont la somme en gamme (1,2)

Étant donné que n est un nombre réel positif dans un tableau, recherchez s'il existe un triplet existe tel que la somme du triplet se situe dans la plage (1, 2). Faites-le en temps linéaire et en espace constant.

  • le tableau n'est pas commandé.
  • les chiffres sont positifs
  • les nombres sont les nombres réels

Toute aide serait grandement appréciée. Merci.

30
Trying

L'astuce consiste à trouver un moyen de catégoriser les solutions possibles et de proposer une solution à espace constant à temps linéaire pour chacune.

Considérons les trois gammes X = (0,2/3), Y = [2/3,1], Z = (1,2). Au plus une valeur peut provenir de Z (si deux valeurs provenaient de Z, alors la somme dépasserait 1+1=2). De même, au moins une valeur doit provenir de X. Supposons qu'il y a 3 valeurs a <= b <= c pour que 1 <= a+b+c <= 2. Ensuite, déterminez quelles classes de solutions possibles sont réalisables:

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` 

Alors, comment pouvons-nous tester chaque cas?

Le cas A est incroyablement facile à tester: la somme est garantie inférieure à 2, il suffit donc de tester la somme la plus grande (3 éléments les plus grands dans X) supérieure à 1.

Le cas C est incroyablement facile à tester: comme la somme est supérieure à 1, il suffit de vérifier si la somme est inférieure à 2. Pour cela, il suffit de tester les 2 valeurs les plus petites dans X et le plus petite valeur dans Z

Les cas D et E sont similaires à C (puisque la somme doit être au moins 4/3> 1, choisissez les valeurs les plus petites possibles dans chaque classe).

Le cas B est le seul cas délicat. 0 < a+b < 4/3 et 2/3 <= c <= 1. Pour traiter le cas B, on considère ces intervalles: X1 = (0, 1/2), X2 = [1/2 2/3), Y = [2/3, 1].

Il en résulte trois cas valides suivants:

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

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

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

Cas B1 et B3: La somme de trois nombres est toujours supérieure à 1. Nous prenons donc les valeurs minimales et vérifions si elles sont inférieures à 2 ou non.

Cas B2: La somme de trois nombres est toujours inférieure à 2, nous prenons donc la somme maximale et vérifions si est supérieur à 1 ou non.

Donc pour résumer, les tests sont:

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

Chaque test peut être effectué en temps linéaire et en espace constant (vous devez seulement trouver Xmax(1), Xmax(2), Xmax(3), Xmin(1), Xmin(2), Ymin(1), Ymin(2), Ymax(1), Zmin(1), qui peuvent tous être trouvés en une seule passe, même si les données ne sont pas triées).

29
Soul Ec

Vous avez donc un tableau de types de données doubles de longueur n. Initialisez trois variables a, b et c en tant que 3 premières valeurs de array.Maintenant, itérez de i = 3 à n et vérifiez les points suivants: 1) Vérifiez si sum est compris entre (1, 2), s'il renvoie alors true. 2) Si ce n'est pas le cas, vérifiez si la somme est supérieure à 2, si c'est le cas, remplacez MAX (a, b, c) par l'élément en cours arr [i]. 3) sinon la somme doit être inférieure à 1 puis remplacer MIN (a, b, c) par l'élément en cours arr [i]. Et enfin, après être sorti de la boucle, vérifier à nouveau le dernier triplet si la somme tombe dans (1,2) puis return true, sinon 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;
}
0
Prince Raj

En me basant sur les idées de @Soul Ec, c’est le code que j’ai proposé. Fonctionne parfaitement bien.

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