On m'a récemment remis cette question d'entrevue et je suis curieux de savoir quelle solution serait la bonne.
Supposons que je reçoive un tableau 2D où tous les les nombres dans le tableau sont en augmentation ordre de gauche à droite et en haut à bas.
Quelle est la meilleure façon de rechercher et déterminer si un numéro cible est dans le tableau?
Maintenant, ma première tendance est d’utiliser une recherche binaire puisque mes données sont triées. Je peux déterminer si un nombre est dans une seule ligne dans le temps O (log N). Cependant, ce sont les 2 directions qui me déconcertent.
Une autre solution qui, à mon avis, pourrait fonctionner est de commencer quelque part au milieu. Si la valeur du milieu est inférieure à ma cible, je peux être sûr que cela se trouve dans la partie carrée de gauche de la matrice à partir du milieu. Je me déplace ensuite en diagonale et vérifie à nouveau, en réduisant la taille du carré dans lequel la cible pourrait potentiellement se trouver jusqu'à ce que je précise le nombre cible.
Quelqu'un a-t-il de bonnes idées pour résoudre ce problème?
Exemple de tableau:
Trié de gauche à droite, de haut en bas.
1 2 4 5 6
2 3 5 7 8
4 6 8 9 10
5 8 9 10 11
Voici une approche simple:
Pour un tableau NxM
, ceci s’exécute dans O(N+M)
. Je pense qu'il serait difficile de faire mieux. :)
Edit: Beaucoup de bonnes discussions. Je parlais du cas général ci-dessus; Clairement, si N
ou M
sont petits, vous pouvez utiliser une approche de recherche binaire pour le faire dans un contexte logarithmique proche.
Voici quelques détails, pour ceux qui sont curieux:
Cet algorithme simple s'appelle un Saddleback Search . Il existe depuis un moment et il est optimal lorsque N == M
. Quelques références:
Cependant, lorsque N < M
, l'intuition suggère que la recherche binaire devrait pouvoir faire mieux que O(N+M)
: Par exemple, lorsque N == 1
, une recherche binaire pure s'exécutera en temps logarithmique plutôt qu'en temps linéaire.
Richard Bird a examiné cette intuition selon laquelle la recherche binaire pourrait améliorer l'algorithme de Saddleback dans un article de 2006:
En utilisant une technique de conversation plutôt inhabituelle, Bird nous montre que pour N <= M
, ce problème a une limite inférieure de Ω(N * log(M/N))
. Cette borne est logique, car elle nous donne des performances linéaires lorsque N == M
et des performances logarithmiques lorsque N == 1
.
Une approche qui utilise une recherche binaire ligne par ligne ressemble à ceci:
N < M
. Disons que N
est des lignes et M
est des colonnes.value
. Si nous le trouvons, nous avons terminé.s
et g
, où s < value < g
.s
est inférieur à value
, nous pouvons donc l'éliminer.g
est supérieur à value
, afin que nous puissions l'éliminer.En termes de complexité dans le cas le plus défavorable, cet algorithme log(M)
supprime la moitié des solutions possibles, puis s’appelle de manière récursive deux fois sur deux problèmes plus petits. Nous devons répéter une version plus petite de ce travail log(M)
pour chaque ligne, mais si le nombre de lignes est faible par rapport au nombre de colonnes, le fait de pouvoir éliminer toutes ces colonnes en temps logarithmique commence à en valoir la peine.
Cela donne à l’algorithme une complexité de T(N,M) = log(M) + 2 * T(M/2, N/2)
, que Bird montre être O(N * log(M/N))
.
Une autre approche publiée par Craig Gidney décrit un algorithme similaire à l’approche ci-dessus: il examine une ligne à la fois en utilisant une taille de pas de M/N
. Son analyse montre que cela entraîne également une performance de O(N * log(M/N))
.
L'analyse Big-O est une bonne chose, mais dans quelle mesure ces approches fonctionnent-elles dans la pratique? Le tableau ci-dessous examine quatre algorithmes pour des tableaux de plus en plus «carrés»:
(L'algorithme "naïf" recherche simplement chaque élément du tableau. L'algorithme "récursif" est décrit ci-dessus. L'algorithme "hybride" est une implémentation de algorithme de Gidney . Pour chaque taille de tableau, la performance a été mesurée en chronométrant chaque algorithme sur un ensemble fixe de 1 000 000 de tableaux générés aléatoirement.)
Quelques points notables:
Une utilisation judicieuse de la recherche binaire peut fournir des performances O(N * log(M/N)
pour les tableaux rectangulaires et carrés. L'algorithme O(N + M)
"saddleback" est beaucoup plus simple, mais souffre de la dégradation des performances car les tableaux deviennent de plus en plus rectangulaires.
Ce problème prend Θ(b lg(t))
time, où b = min(w,h)
et t=b/max(w,h)
. Je discute de la solution dans cet article de blog .
Borne inférieure
Un adversaire peut forcer un algorithme à faire des requêtes Ω(b lg(t))
, en se limitant à la diagonale principale:
Légende: les cellules blanches sont des éléments plus petits, les cellules grises sont des éléments plus grands, les cellules jaunes sont des éléments plus petits ou identiques et les cellules orange sont des éléments plus grands ou égaux L'adversaire force la solution à choisir la cellule jaune ou orange dans laquelle l'algorithme pose la dernière question.
Notez qu'il existe b
listes triées indépendantes de taille t
, nécessitant d'éliminer complètement les requêtes Ω(b lg(t))
.
Algorithme
w >= h
)t
située à gauche du coin supérieur droit de la zone valide t
restantes de la ligne avec une recherche binaire. Si un élément correspondant est trouvé, renvoyez-le avec sa position.t
courtes.Trouver un article:
Déterminer un article n'existe pas:
Légende: les cellules blanches sont des éléments plus petits, les cellules grises sont des éléments plus grands et la cellule verte est un élément identique.
Une analyse
b*t
colonnes courtes à éliminer. Il y a b
longues lignes à éliminer. L'élimination d'une longue ligne coûte O(lg(t))
time. L'élimination des t
colonnes courtes coûte O(1)
time.
Dans le pire des cas, nous devrons éliminer chaque colonne et chaque ligne en prenant le temps O(lg(t)*b + b*t*1/t) = O(b lg(t))
.
Notez que je suppose que lg
se fixe à un résultat supérieur à 1 (c'est-à-dire lg(x) = log_2(max(2,x))
). C'est pourquoi, lorsque w=h
, ce qui signifie t=1
, nous obtenons la limite attendue de O(b lg(1)) = O(b) = O(w+h)
.
Code
public static Tuple<int, int> TryFindItemInSortedMatrix<T>(this IReadOnlyList<IReadOnlyList<T>> grid, T item, IComparer<T> comparer = null) {
if (grid == null) throw new ArgumentNullException("grid");
comparer = comparer ?? Comparer<T>.Default;
// check size
var width = grid.Count;
if (width == 0) return null;
var height = grid[0].Count;
if (height < width) {
var result = grid.LazyTranspose().TryFindItemInSortedMatrix(item, comparer);
if (result == null) return null;
return Tuple.Create(result.Item2, result.Item1);
}
// search
var minCol = 0;
var maxRow = height - 1;
var t = height / width;
while (minCol < width && maxRow >= 0) {
// query the item in the minimum column, t above the maximum row
var luckyRow = Math.Max(maxRow - t, 0);
var cmpItemVsLucky = comparer.Compare(item, grid[minCol][luckyRow]);
if (cmpItemVsLucky == 0) return Tuple.Create(minCol, luckyRow);
// did we eliminate t rows from the bottom?
if (cmpItemVsLucky < 0) {
maxRow = luckyRow - 1;
continue;
}
// we eliminated most of the current minimum column
// spend lg(t) time eliminating rest of column
var minRowInCol = luckyRow + 1;
var maxRowInCol = maxRow;
while (minRowInCol <= maxRowInCol) {
var mid = minRowInCol + (maxRowInCol - minRowInCol + 1) / 2;
var cmpItemVsMid = comparer.Compare(item, grid[minCol][mid]);
if (cmpItemVsMid == 0) return Tuple.Create(minCol, mid);
if (cmpItemVsMid > 0) {
minRowInCol = mid + 1;
} else {
maxRowInCol = mid - 1;
maxRow = mid - 1;
}
}
minCol += 1;
}
return null;
}
J'utiliserais la stratégie diviser pour mieux régner pour ce problème, semblable à ce que vous avez suggéré, mais les détails sont un peu différents.
Ce sera une recherche récursive sur les sous-gammes de la matrice.
À chaque étape, choisissez un élément au milieu de la plage. Si la valeur trouvée correspond à ce que vous recherchez, vous avez terminé.
Sinon, si la valeur trouvée est inférieure à la valeur que vous recherchez, vous savez alors qu'elle ne se trouve pas dans le quadrant situé au-dessus et à gauche de votre position actuelle. Vous devez donc effectuer une recherche récursive dans les deux sous-catégories: tout (exclusivement) en dessous de la position actuelle et tout (exclusivement) vers la droite correspondant ou au-dessus de la position actuelle.
Sinon, (la valeur trouvée est supérieure à la valeur que vous recherchez), vous savez que ce n'est pas dans le quadrant en dessous et à droite de votre position actuelle. Vous devez donc effectuer une recherche récursive dans les deux sous-plages: tout (exclusivement) à gauche de la position actuelle et tout (exclusivement) au-dessus de la position actuelle figurant dans la colonne en cours ou dans une colonne à droite.
Et ba-da-bing, vous l'avez trouvé.
Notez que chaque appel récursif ne traite que de la sous-gamme actuelle, pas (par exemple) TOUTES les lignes au-dessus de la position actuelle. Juste ceux de la sous-gamme actuelle.
Voici quelques pseudocodes pour vous:
bool numberSearch(int[][] arr, int value, int minX, int maxX, int minY, int maxY)
if (minX == maxX and minY == maxY and arr[minX,minY] != value)
return false
if (arr[minX,minY] > value) return false; // Early exits if the value can't be in
if (arr[maxX,maxY] < value) return false; // this subrange at all.
int nextX = (minX + maxX) / 2
int nextY = (minY + maxY) / 2
if (arr[nextX,nextY] == value)
{
print nextX,nextY
return true
}
else if (arr[nextX,nextY] < value)
{
if (numberSearch(arr, value, minX, maxX, nextY + 1, maxY))
return true
return numberSearch(arr, value, nextX + 1, maxX, minY, nextY)
}
else
{
if (numberSearch(arr, value, minX, nextX - 1, minY, maxY))
return true
reutrn numberSearch(arr, value, nextX, maxX, minY, nextY)
}
Jusqu'ici, les deux réponses principales semblent être la méthode O(log N)
"Méthode ZigZag" et la méthode O(N+M)
Binary Search. Je pensais faire des tests en comparant les deux méthodes avec différentes configurations. Voici les détails:
La matrice est N x N carré dans chaque test, N variant de 125 à 8 000 (la plus grande pile que ma machine virtuelle Java puisse gérer). Pour chaque taille de tableau, j'ai choisi un emplacement aléatoire dans le tableau pour mettre un seul 2
. Je mets ensuite un 3
partout où cela est possible (à droite et en dessous du 2), puis je remplis le reste du tableau avec 1
. Certains des commentateurs précédents semblaient penser que ce type d’installation produirait un temps d’exécution pire pour les deux algorithmes. Pour chaque taille de tableau, j'ai sélectionné 100 emplacements aléatoires différents pour le 2 (cible de recherche) et exécuté le test. J'ai enregistré le temps d'exécution moyen et le pire temps d'exécution pour chaque algorithme. Comme cela se produisait trop rapidement pour obtenir de bonnes lectures ms en Java et parce que je ne fais pas confiance à nanoTime () de Java, j'ai répété chaque test 1 000 fois simplement pour ajouter un facteur de biais uniforme à toutes les époques. Voici les résultats:
ZigZag a battu le binaire à chaque test pour les temps moyen et moyen, mais ils sont tous plus ou moins identiques.
Voici le code Java:
public class SearchSortedArray2D {
static boolean findZigZag(int[][] a, int t) {
int i = 0;
int j = a.length - 1;
while (i <= a.length - 1 && j >= 0) {
if (a[i][j] == t) return true;
else if (a[i][j] < t) i++;
else j--;
}
return false;
}
static boolean findBinarySearch(int[][] a, int t) {
return findBinarySearch(a, t, 0, 0, a.length - 1, a.length - 1);
}
static boolean findBinarySearch(int[][] a, int t,
int r1, int c1, int r2, int c2) {
if (r1 > r2 || c1 > c2) return false;
if (r1 == r2 && c1 == c2 && a[r1][c1] != t) return false;
if (a[r1][c1] > t) return false;
if (a[r2][c2] < t) return false;
int rm = (r1 + r2) / 2;
int cm = (c1 + c2) / 2;
if (a[rm][cm] == t) return true;
else if (a[rm][cm] > t) {
boolean b1 = findBinarySearch(a, t, r1, c1, r2, cm - 1);
boolean b2 = findBinarySearch(a, t, r1, cm, rm - 1, c2);
return (b1 || b2);
} else {
boolean b1 = findBinarySearch(a, t, r1, cm + 1, rm, c2);
boolean b2 = findBinarySearch(a, t, rm + 1, c1, r2, c2);
return (b1 || b2);
}
}
static void randomizeArray(int[][] a, int N) {
int ri = (int) (Math.random() * N);
int rj = (int) (Math.random() * N);
a[ri][rj] = 2;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (i == ri && j == rj) continue;
else if (i > ri || j > rj) a[i][j] = 3;
else a[i][j] = 1;
}
}
}
public static void main(String[] args) {
int N = 8000;
int[][] a = new int[N][N];
int randoms = 100;
int repeats = 1000;
long start, end, duration;
long zigMin = Integer.MAX_VALUE, zigMax = Integer.MIN_VALUE;
long binMin = Integer.MAX_VALUE, binMax = Integer.MIN_VALUE;
long zigSum = 0, zigAvg;
long binSum = 0, binAvg;
for (int k = 0; k < randoms; k++) {
randomizeArray(a, N);
start = System.currentTimeMillis();
for (int i = 0; i < repeats; i++) findZigZag(a, 2);
end = System.currentTimeMillis();
duration = end - start;
zigSum += duration;
zigMin = Math.min(zigMin, duration);
zigMax = Math.max(zigMax, duration);
start = System.currentTimeMillis();
for (int i = 0; i < repeats; i++) findBinarySearch(a, 2);
end = System.currentTimeMillis();
duration = end - start;
binSum += duration;
binMin = Math.min(binMin, duration);
binMax = Math.max(binMax, duration);
}
zigAvg = zigSum / randoms;
binAvg = binSum / randoms;
System.out.println(findZigZag(a, 2) ?
"Found via zigzag method. " : "ERROR. ");
//System.out.println("min search time: " + zigMin + "ms");
System.out.println("max search time: " + zigMax + "ms");
System.out.println("avg search time: " + zigAvg + "ms");
System.out.println();
System.out.println(findBinarySearch(a, 2) ?
"Found via binary search method. " : "ERROR. ");
//System.out.println("min search time: " + binMin + "ms");
System.out.println("max search time: " + binMax + "ms");
System.out.println("avg search time: " + binAvg + "ms");
}
}
Ceci est une courte preuve de la limite inférieure du problème.
Vous ne pouvez pas le faire mieux que le temps linéaire (en termes de dimensions de tableau, pas de nombre d'éléments). Dans le tableau ci-dessous, chacun des éléments marqués avec *
peut être 5 ou 6 (indépendamment des autres). Donc, si votre valeur cible est 6 (ou 5), l'algorithme doit toutes les examiner.
1 2 3 4 *
2 3 4 * 7
3 4 * 7 8
4 * 7 8 9
* 7 8 9 10
Bien sûr, cela s’étend également à de plus grands tableaux. Cela signifie que cette réponse est optimale.
Mise à jour: comme l'a souligné Jeffrey L. Whitledge, elle n'est optimale que comme limite inférieure asymptotique du temps d'exécution par rapport à la taille des données d'entrée (traitée comme une variable unique). Le temps d'exécution traité comme une fonction à deux variables sur les deux dimensions du tableau peut être amélioré.
Je pense que voici la réponse et cela fonctionne pour tout type de matrice triée
bool findNum(int arr[][ARR_MAX],int xmin, int xmax, int ymin,int ymax,int key)
{
if (xmin > xmax || ymin > ymax || xmax < xmin || ymax < ymin) return false;
if ((xmin == xmax) && (ymin == ymax) && (arr[xmin][ymin] != key)) return false;
if (arr[xmin][ymin] > key || arr[xmax][ymax] < key) return false;
if (arr[xmin][ymin] == key || arr[xmax][ymax] == key) return true;
int xnew = (xmin + xmax)/2;
int ynew = (ymin + ymax)/2;
if (arr[xnew][ynew] == key) return true;
if (arr[xnew][ynew] < key)
{
if (findNum(arr,xnew+1,xmax,ymin,ymax,key))
return true;
return (findNum(arr,xmin,xmax,ynew+1,ymax,key));
} else {
if (findNum(arr,xmin,xnew-1,ymin,ymax,key))
return true;
return (findNum(arr,xmin,xmax,ymin,ynew-1,key));
}
}
Question interessante. Considérez cette idée - créez une limite où tous les nombres sont supérieurs à votre cible et une autre où tous les nombres sont inférieurs à votre cible. S'il reste quelque chose entre les deux, c'est votre cible.
Si je cherche 3 dans votre exemple, je lis sur la première ligne jusqu'à ce que je frappe 4, puis je cherche le plus petit nombre adjacent (y compris les diagonales) supérieur à 3:
1 2 4 5 6
2 3 5 7 8
4 6 8 9 10
5 8 9 10 11
Maintenant, je fais la même chose pour les nombres inférieurs à 3:
1 2 4 5 6
2 3 5 7 8
4 6 8 9 10
5 8 9 10 11
Maintenant, je demande s'il y a quelque chose à l'intérieur des deux limites Si oui, cela doit être 3. Si non, alors il n'y a pas 3. Comme indirect, puisque je ne trouve pas le nombre, je déduis juste qu'il doit être là. Cela a le bonus supplémentaire de compter TOUS les 3.
J'ai essayé ceci sur quelques exemples et cela semble fonctionner correctement.
La recherche binaire à travers la diagonale du tableau est la meilleure option ..__ Nous pouvons déterminer si l'élément est inférieur ou égal aux éléments de la diagonale.
Je suggère, stockez tous les caractères dans un 2D list
. puis recherchez l’index de l’élément requis s’il existe dans la liste.
Si non présent, imprimer le message approprié, sinon, imprimer la ligne et la colonne comme suit:
row = (index/total_columns)
et column = (index%total_columns -1)
Cela n'engendrera que le temps de recherche binaire dans une liste.
S'il vous plaît suggérer des corrections. :)
A. Effectuez une recherche binaire sur les lignes où le numéro cible peut être indiqué.
B. Faites-en un graphique: recherchez le nombre en prenant toujours le plus petit noeud voisin non visité et en effectuant un retour arrière lorsqu'un nombre trop grand est trouvé
La recherche binaire serait la meilleure approche, imo. À partir de 1/2 x, 1/2 y le coupera en deux. IE un carré de 5x5 serait quelque chose comme x == 2/y == 3. J'ai arrondi une valeur vers le bas et une valeur vers le haut pour mieux définir la direction de la valeur ciblée.
Pour plus de clarté, la prochaine itération vous donnerait quelque chose comme x == 1/y == 2 OR x == 3/y == 5
Si la solution O (M log (N)) convient pour un tableau MxN -
template <size_t n>
struct MN * get(int a[][n], int k, int M, int N){
struct MN *result = new MN;
result->m = -1;
result->n = -1;
/* Do a binary search on each row since rows (and columns too) are sorted. */
for(int i = 0; i < M; i++){
int lo = 0; int hi = N - 1;
while(lo <= hi){
int mid = lo + (hi-lo)/2;
if(k < a[i][mid]) hi = mid - 1;
else if (k > a[i][mid]) lo = mid + 1;
else{
result->m = i;
result->n = mid;
return result;
}
}
}
return result;
}
Démonstration de travail en C++.
S'il vous plaît, faites-moi savoir si cela ne fonctionnerait pas ou s'il y avait un bug là-dessus.
public boolean searchSortedMatrix(int arr[][] , int key , int minX , int maxX , int minY , int maxY){
// base case for recursion
if(minX > maxX || minY > maxY)
return false ;
// early fails
// array not properly intialized
if(arr==null || arr.length==0)
return false ;
// arr[0][0]> key return false
if(arr[minX][minY]>key)
return false ;
// arr[maxX][maxY]<key return false
if(arr[maxX][maxY]<key)
return false ;
//int temp1 = minX ;
//int temp2 = minY ;
int midX = (minX+maxX)/2 ;
//if(temp1==midX){midX+=1 ;}
int midY = (minY+maxY)/2 ;
//if(temp2==midY){midY+=1 ;}
// arr[midX][midY] = key ? then value found
if(arr[midX][midY] == key)
return true ;
// alas ! i have to keep looking
// arr[midX][midY] < key ? search right quad and bottom matrix ;
if(arr[midX][midY] < key){
if( searchSortedMatrix(arr ,key , minX,maxX , midY+1 , maxY))
return true ;
// search bottom half of matrix
if( searchSortedMatrix(arr ,key , midX+1,maxX , minY , maxY))
return true ;
}
// arr[midX][midY] > key ? search left quad matrix ;
else {
return(searchSortedMatrix(arr , key , minX,midX-1,minY,midY-1));
}
return false ;
}
MODIFIER:
J'ai mal compris la question. Comme le soulignent les commentaires, cela ne fonctionne que dans le cas le plus restreint.
Dans un langage tel que C qui stocke les données dans un ordre de lignes majeur, traitez-le simplement comme un tableau 1D de taille n * m et utilisez une recherche binaire.
Eh bien, pour commencer, supposons que nous utilisons un carré.
1 2 3
2 3 4
3 4 5
1. Recherche d'un carré
Je voudrais utiliser une recherche binaire sur la diagonale. L’objectif est de localiser le plus petit nombre qui n’est pas strictement inférieur au nombre cible.
Supposons que je recherche 4
par exemple, puis je finirais par localiser 5
à (2,2)
.
Ensuite, je suis assuré que si 4
est dans la table, sa position est (x,2)
ou (2,x)
avec x
dans [0,2]
. Eh bien, c'est juste 2 recherches binaires.
La complexité n’est pas décourageante: O(log(N))
(3 recherches binaires sur des plages de longueur N
)
2. Rechercher un rectangle, approche naïve
Bien sûr, cela devient un peu plus compliqué lorsque N
et M
diffèrent (avec un rectangle), considérons ce cas dégénéré:
1 2 3 4 5 6 7 8
2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17
Et disons que je cherche 9
... L’approche diagonale est toujours bonne, mais la définition de la diagonale change. Ici, ma diagonale est [1, (5 or 6), 17]
. Supposons que j'ai pris [1,5,17]
, alors je sais que si 9
est dans la table, il est soit dans la sous-partie:
5 6 7 8
6 7 8 9
10 11 12 13 14 15 16
Cela nous donne 2 rectangles:
5 6 7 8 10 11 12 13 14 15 16
6 7 8 9
Alors on peut recurse! en commençant probablement par celui avec moins d'éléments (bien que dans ce cas, il nous tue).
Je dois préciser que si l’une des dimensions est inférieure à 3
, nous ne pouvons pas appliquer les méthodes diagonales et nous devons utiliser une recherche binaire. Ici, cela voudrait dire:
10 11 12 13 14 15 16
, introuvable5 6 7 8
, introuvable6 7 8 9
, introuvableC'est délicat car pour obtenir de bonnes performances, il peut être utile de différencier plusieurs cas, en fonction de la forme générale ....
3. Recherche d'un rectangle, approche brutale
Ce serait beaucoup plus facile si nous avions affaire à un carré ... alors mettons les choses au clair.
1 2 3 4 5 6 7 8
2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17
17 . . . . . . 17
. .
. .
. .
17 . . . . . . 17
Nous avons maintenant un carré.
Bien sûr, nous ne créerons probablement PAS ces lignes, nous pourrions simplement les imiter.
def get(x,y):
if x < N and y < M: return table[x][y]
else: return table[N-1][M-1] # the max
il se comporte donc comme un carré sans occuper plus de mémoire (au détriment de la vitesse, probablement en fonction de la mémoire cache ... ah bon: p)
J'ai une solution Divide & Conquer récursive . L'idée de base pour une étape est la suivante: Nous savons que le Left-Upper (LU) est le plus petit et que le right-bottom (RB) est le plus grand no. N) doit: N> = LU et N <= RB
SI N == LU et N == RB :::: Élément trouvé et Abort renvoyant la position/Index Si N> = LU et N <= RB = FALSE, Non n'est pas là et abandonne . Si N> = LU et N <= RB = TRUE, divisez le tableau 2D en 4 parties égales du tableau 2D, chacune de manière logique .. Et appliquez ensuite le même pas d'algo aux quatre sous-tableaux.
Mon Algo est correct, j'ai implémenté sur mon PC d'amis . Complexité: chaque 4 comparaisons peuvent être utilisées pour déduire le nombre total d'éléments à un quart dans le pire des cas .. Ma complexité devient donc 1 + 4 x lg (n) + 4 Mais je m'attendais vraiment à ce que cela fonctionne sur O (n)
Je pense que quelque chose ne va pas quelque part dans mon calcul de complexité, corrigez s'il vous plaît si oui.
La solution optimale consiste à commencer par le coin supérieur gauche, qui a une valeur minimale. Déplacez-vous en diagonale vers le bas à droite jusqu'à atteindre un élément dont la valeur> = valeur de l'élément donné. Si la valeur de l'élément est égale à celle de l'élément donné, retourne trouvé comme vrai.
Sinon, à partir de là, nous pouvons procéder de deux manières.
Stratégie 1:
Stratégie 2: Soit i l’indice de la ligne et j l’indice de la colonne de la diagonale à laquelle nous nous sommes arrêtés. (Ici, nous avons i = j, BTW). Soit k = 1.
1 2 4 5 6
2 3 5 7 8
4 6 8 9 10
5 8 9 10 11