Étant donné que chaque tableau contient N tableaux de taille K, chacun de ces éléments K est trié, chacun de ces éléments N * K est unique. Choisissez un seul élément dans chacun des N tableaux du sous-ensemble choisi de N éléments. Soustrayez les éléments minimum et maximum. Maintenant, cette différence Devrait être la moins petite possible. Espérons que le problème est clair :) :)
Échantillon:
N=3, K=3
N=1 : 6, 16, 67
N=2 : 11,17,68
N=3 : 10, 15, 100
ici si on choisit 16, 17, 15, on obtient la différence minimale de 17-15 = 2.
Je peux penser à O (N * K * N) (édité après que correctement souligné par zivo, pas une bonne solution maintenant :() solution.
1. Prenez le pointeur N qui pointe initialement vers l'élément initial de chacun des N tableaux.
6, 16, 67
^
11,17,68
^
10, 15, 100
^
2. Recherchez l'élément le plus élevé et le plus faible parmi le pointeur actuel O(k) (6 et 11) et calculez la différence entre eux (5).
3. Incrémentez le pointeur qui pointe vers l'élément le plus bas de 1 dans ce tableau.
6, 16, 67
^
11,17,68
^
10, 15, 100 (difference:5)
^
4. Répétez les étapes 2 et 3 et enregistrez la différence minimale.
6, 16, 67
^
11,17,68
^
10,15,100 (difference:5)
^
6, 16, 67
^
11,17,68
^
10,15,100 (difference:2)
^
Ci-dessus sera la solution requise.
6, 16, 67
^
11,17,68
^
10,15,100 (difference:84)
^
6, 16, 67
^
11,17,68
^
10,15,100 (difference:83)
^
Etc......
Sa complexité peut être réduite en utilisant un tas (comme suggéré par Uri). J'y ai pensé, mais j'ai rencontré un problème: chaque fois qu'un élément est extrait du tas, son numéro de tableau doit être trouvé afin d'incrémenter le pointeur correspondant pour ce tableau. Un moyen efficace de trouver un numéro de tableau peut certainement réduire la complexité à O (K * N log (K * N)) . Une méthode naïve consiste à utiliser une structure de données comme celle-ci.
Struct
{
int element;
int arraynumer;
}
et reconstruire les données initiales comme
6|0,16|0,67|0
11|1,17|1,68|1
10|2,15|2,100|2
Conservez initialement le maximum actuel pour la première colonne et insérez les éléments pointés dans le tas. Désormais, chaque fois qu'un élément est extrait, son numéro de tableau peut être trouvé, le pointeur de ce tableau étant incrémenté, le nouvel élément pointé peut être comparé au pointeur maximum et au pointeur actuel ajusté en conséquence.
Voici donc un algorithme pour résoudre ce problème en deux étapes:
La première étape consiste à fusionner tous vos tableaux en un tableau trié qui pourrait ressembler à ceci:
combine_val [] - qui contient tous les nombres
combine_ind [] - qui contient l'index du tableau auquel ce numéro appartenait à l'origine
cette étape peut être réalisée facilement en O (K * N * log (N)) mais je pense que vous pouvez faire mieux que cela aussi (peut-être pas, vous pouvez rechercher des variantes de tri par fusion car elles sont similaires à celles-ci)
Maintenant deuxième étape:
il est plus facile de simplement mettre du code au lieu d'expliquer, voici donc le pseduocode:
int count[N] = { 0 }
int head = 0;
int diffcnt = 0;
// mindiff is initialized to overall maximum value - overall minimum value
int mindiff = combined_val[N * K - 1] - combined_val[0];
for (int i = 0; i < N * K; i++)
{
count[combined_ind[i]]++;
if (count[combined_ind[i]] == 1) {
// diffcnt counts how many arrays have at least one element between
// indexes of "head" and "i". Once diffcnt reaches N it will stay N and
// not increase anymore
diffcnt++;
} else {
while (count[combined_ind[head]] > 1) {
// We try to move head index as forward as possible while keeping diffcnt constant.
// i.e. if count[combined_ind[head]] is 1, then if we would move head forward
// diffcnt would decrease, that is something we dont want to do.
count[combined_ind[head]]--;
head++;
}
}
if (diffcnt == N) {
// i.e. we got at least one element from all arrays
if (combined_val[i] - combined_val[head] < mindiff) {
mindiff = combined_val[i] - combined_val[head];
// if you want to save actual numbers too, you can save this (i.e. i and head
// and then extract data from that)
}
}
}
le résultat est inattendu.
Le temps d'exécution de la deuxième étape est O (N * K). En effet, l'index "tête" ne se déplace que de N * K fois au maximum. donc la boucle interne ne fait pas ce quadratique, il est toujours linéaire.
Le temps total d'exécution de l'algorithme est donc O (N * K * log (N)). Cependant, cela est dû à l'étape de fusion. Si vous pouvez obtenir une meilleure étape de fusion, vous pouvez probablement le réduire à O (N * K).
Ce problème est pour les gestionnaires
Vous avez 3 développeurs (N1), 3 testeurs (N2) et 3 administrateurs de base de données (N3) Choisissez l'équipe la moins divergente qui peut exécuter un projet avec succès.
int[n] result;// where result[i] keeps the element from bucket N_i
int[n] latest;//where latest[i] keeps the latest element visited from bucket N_i
Iterate elements in (N_1 + N_2 + N_3) in sorted order
{
Keep track of latest element visited from each bucket N_i by updating 'latest' array;
if boundary(latest) < boundary(result)
{
result = latest;
}
}
int boundary(int[] array)
{
return Max(array) - Min(array);
}
Supposons que l'algorithme trouve une série A = <A [1], A [2], ..., A [N]> qui n'est pas la solution optimale (R).
Considérons l'indice j dans R, tel que l'item R [j] soit le premier item parmi R que l'algorithme examine et le remplace par l'item suivant dans sa ligne.
Soit A 'la solution candidate à cette phase (avant le remplacement). Puisque R [j] = A '[j] est la valeur minimale de A', c'est également le minimum de R. Considérons maintenant la valeur maximale de R, R [m]. Si A '[m] <R [m], alors R peut être amélioré en remplaçant R [m] par A' [m], ce qui contredit le fait que R est optimal. Par conséquent, A '[m] = R [m]. En d’autres termes, R et A 'partagent les mêmes maximum et minimum, ils sont donc équivalents. Ceci complète la preuve: si R est une solution optimale, alors l’algorithme trouvera une solution aussi bonne que R.
J'ai O (K * N * log (K)), avec une exécution typique beaucoup moins. Actuellement, je ne peux rien penser de mieux. Je vais d'abord expliquer le plus facile à décrire (exécution un peu plus longue):
Cet algorithme peut être optimisé si, pour chaque tableau, vous ajoutez un nouvel index de plancher. Lorsque vous effectuez la recherche binaire, effectuez une recherche entre les niveaux 'Floor' à 'K-1'. Une fois que vous avez trouvé un élément le plus proche de 'f', mettez à jour l'index de plancher avec l'index de cet élément. Le pire cas est identique (Floor ne peut pas être mis à jour si l'élément maximum du premier tableau est plus petit que tout autre minimum), mais le cas moyen s'améliorera.
pour chaque élément du 1er tableau
choose the element in 2nd array that is closest to the element in 1st array
current_array = 2;
do
{
choose the element in current_array+1 that is closest to the element in current_array
current_array++;
} while(current_array < n);
complexité: O (k ^ 2 * n)
Voici ma logique sur la façon de résoudre ce problème, en gardant à l’esprit que nous devons choisir un élément dans chacun des N tableaux (pour calculer le minimum).
// if we take the above values as an example!
// then the idea would be to sort all three arrays while keeping another
// array to keep the reference to their sets (1 or 2 or 3, could be
// extended to n sets)
1 3 2 3 1 2 1 2 3 // this is the array that holds the set index
6 10 11 15 16 17 67 68 100 // this is the sorted combined array.
| |
5 2 33 // this is the computed least minimum,
// the rule is to make sure the indexes of the values
// we are comparing are different (to make sure we are
// comparing elements from different sets), then for example
// the first element of that example is index:1|value:6 we hold
// that value 6 (that is the value we will be using to compute the least minimum,
// then we go to the Edge of the comparison which would be the second different index,
// we skip index:3|value:10 (we remove it from the array) we compare index:2|value:11
// to index:1|value:6 we obtain 5 which would go to a variable named leastMinimum = 5,
// now we remove the indexes and values we already used,
// and redo the same steps.
Étape 1 :
1 3 2 3 1 2 1 2 3
6 10 11 15 16 17 67 68 100
|
5
leastMinumum = 5
Étape 2:
3 1 2 1 2 3
15 16 17 67 68 100
|
2
leastMinimum = min(2, leastMinumum) // which is equal 2
Étape 3:
1 2 3
67 68 100
33
leastMinimum = min(33, leastMinumum) // which is equal to old leastMinumum which is 2
Maintenant: nous supposons que les éléments du même tableau sont très proches les uns des autres (k = 2 cette fois, ce qui signifie que nous n’avons que 3 ensembles avec deux valeurs):
// After sorting the n arrays we will have the below indexes array and values array
1 1 2 3 2 3
6 7 8 12 15 16
* * *
* we skip second index of 1|7 and we take the least minimum of 1|6 and 3|12 (index:2|value:8 will be removed as it is not at the edges, we pick the minimum and maximum of the unique index subset of n elements)
1 3
6 12
=6
* second step we remove the values we already used, so the array become like below:
1 2 3
7 15 16
* * *
7 - 16
= 9
Remarque: Une autre approche consommant plus de mémoire consisterait à créer N sous-tableaux à partir desquels nous comparerions le maximum - minumum.
Ainsi, à partir du tableau de valeurs triées ci-dessous et de son tableau d'index correspondants, nous extrayons trois autres sous-tableaux:
1 3 2 3 1 2 1 2 3
6 10 11 15 16 17 67 68 100
Premier tableau:
1 3 2
6 10 11
11-6 = 5
Deuxième tableau:
3 1 2
15 15 17
17-15 = 2
Troisième tableau:
1 2 3
67 68 100
100 - 67 = 33