【Offre de doigt d'épée】 —— Résumé d'exemple relatif à la recherche binaire

Tout d'abord, la valeur minimale de la matrice tournante

Exigences du sujet:

Déplacez les premiers éléments d'un tableau à la fin du tableau, nous l'appelons la rotation du tableau.
Entrez une rotation d'un tableau trié non décroissant et sortez le plus petit élément du tableau pivoté.
Par exemple, le tableau {3,4,5,1,2} est une rotation de {1,2,3,4,5}, et la valeur minimale du tableau est 1.
REMARQUE: Tous les éléments donnés sont supérieurs à 0, si la taille du tableau est 0, veuillez retourner 0.

Analyse thématique:

Tout d'abord, nous pouvons préciser que le tableau
après la rotation du tableau de rotation peut en fait être divisé en deux sous-tableaux triés, et les éléments du sous-tableau avant sont supérieurs ou égaux aux éléments du sous-tableau arrière,
nous pouvons donc suivre ceci Il est temps d’explorer les réponses aux questions. Nous analysons toujours d'une manière simple et facile à comprendre avec des exemples spécifiques.

Cas 1: le
tableau {3, 4, 5, 1, 2} est utilisé comme colonne. Définissez d'abord deux pointeurs pour pointer vers le premier élément et le dernier élément du tableau. La partie ombrée est le deuxième sous-tableau.
Insérez la description de l'image ici
Calculez l' indice de l'élément du milieu à ce moment = (0 + 4) / 2 = 2. La valeur de l'élément du tableau avec l'indice 2 est 5. Puisque 5> le nombre 3 pointé par p1, la valeur du milieu est dans le premier sous-tableau . Pointez p1 sur le chiffre du milieu.
Insérez la description de l'image ici
À ce moment, le nombre 1 au milieu de p1 et p2 est plus petit que le nombre pointé par p2. Le nombre au milieu est dans le deuxième sous-tableau. Pointez p2 sur le chiffre du milieu.
Insérez la description de l'image ici
À ce moment, p1 et p2 pointent vers deux nombres adjacents , puis
p2
pointe vers le plus petit nombre du tableau .
Pourquoi p2 est-il le plus petit nombre?
Parce que lorsque les deux pointeurs sont à une seule position l'un de l'autre, cela indique que p1 a déjà pointé vers le dernier élément du premier tableau croissant et que p2 a pointé vers le premier élément du deuxième tableau croissant. Donc, ce que p2 pointe est le plus petit élément du tableau.

Cas 2:
Lorsque vous rencontrez la situation où p1, p2 et le nombre pointé par le pointeur du milieu sont les mêmes, comme le tableau {0,1,1,1,1}. {1,0,1,1,1} et {1,1,1,0,1} sont la rotation du tableau incrémentiel
Insérez la description de l'image ici
comme illustré dans la figure ci-dessus. Dans ce cas, il n'est pas clair à quel tableau incrémentiel appartient l'élément central. , Vous devez donc emprunter la voie de la recherche séquentielle.

Cas 3:
si les 0 premiers éléments du tableau trié sont déplacés à la fin, c'est-à-dire le tableau lui-même, il s'agit toujours d'une rotation du tableau.
Dans ce cas, renvoyez simplement l'élément pointé par p1. C'est pourquoi indexMid est affecté à p1.

Implémentation du code

int MinInOrder(int* numbers, int p1, int p2)
{
    int result = numbers[p1];
    for (int i = p1 + 1; i <= p2; i++)
    {
        if (result > numbers[i])
            result = numbers[i];
    }
    return result;
}
int Min(int* numbers, int length)
{
	if (numbers == nullptr || length <= 0)
		throw new::std::exception("Invalid parameters");

	int p1 = 0;
	int p2 = length - 1;
	int indexmid = p1;
	while (numbers[p1] >= numbers[p2])
	{
		//情况一
		if (p2 - p1 == 1)
		{
			indexmid = p2;
			break;
		}
		indexmid = (p1 + p2) / 2;

		//情况二
		if (numbers[p1] == numbers[p2] == numbers[indexmid])
		{
			return MinInOrder(numbers, p1, p2);
		}
		//缩小范围
		if (numbers[indexmid] >= numbers[p1])
			p1 = indexmid;
		else if(numbers[indexmid] <= numbers[p2])
			p2 = indexmid;
	}
	return numbers[indexmid];
}

Deuxièmement, trouvez le nombre dans le tableau trié

Sujet 1: Le nombre de fois qu'un nombre apparaît dans un tableau trié

Comptez le nombre de fois qu'un nombre apparaît dans un tableau trié. Par exemple, saisissez le tableau trié {1,2,3,3,3,3,4,5} et le nombre 3, car 3 apparaît 4 fois dans ce tableau, donc sortez 4.

Analyse:
Puisque le tableau est ordonné, nous pensons naturellement à utiliser la recherche binaire. Il est préférable d'utiliser une recherche binaire pour trouver un 3, puis de numériser séquentiellement sur les côtés gauche et droit de 3 pour trouver respectivement les 3 premiers et les 3 derniers.

Trouvez les 3 premiers du tableau: Le
numéro 3 a été trouvé sur la base de la recherche binaire ci-dessus, mais il n'est pas clair si ce 3 est le premier 3 du tableau. Par conséquent, nous devons juger un nombre avant 3.
Insérez la description de l'image ici
Si X dans la figure, si X n'est pas 3, alors les 3 premiers du tableau sont ceux qui viennent d'être trouvés 3.
Si X dans la figure est 3, alors le premier 3 Doit être dans la première moitié du tableau, nous devons toujours rechercher dans la première moitié du tableau au prochain tour.
Le code est implémenté comme suit:

int GetFirstK(int* data, int length, int k, int start, int end)
{
    if (start > end)
        return -1;
    int mid = (start + end) / 2;
    int middleData = data[mid];

    if (middleData == k)
    {
        if ((mid > 0 && data[mid - 1] != k) || mid == 0)
            return mid;
        else
            end = mid - 1;
    }
    else if (middleData > k)
    {
        end = mid - 1;
    }
    else
    start = mid + 1;
    return GetFirstK(data, length, k, start, end);
}

Non trouvé 3 renvoie -1, le premier 3 du tableau renvoie son indice

Trouvez les 3 derniers dans le tableau:
La méthode pour trouver les 3 derniers est similaire à la précédente, le code écrit basé sur la récursivité est le suivant:

int GetLastK(int* data, int length, int k, int start, int end)
{
    if (start > end)
        return -1;
    int mid = (start + end) / 2;
    int middleData = data[mid];
    if (middleData == k)
    {
        if ((mid < length-1 && data[mid + 1] != k) || mid == length-1)
            return mid;
        else
            start = mid + 1;
    }
    else if (middleData < k)
    {
        start = mid + 1;
    }
    else
      end = mid - 1;
    return GetLastK(data, length, k, start, end);
}

Après avoir trouvé les indices des 3 premiers et des 3 derniers dans le tableau, le nombre d'occurrences dans le tableau peut être calculé. Le code est le suivant:

int GetNumberOfK(int* data, int length, int k)
{
    int count = 0;
    if (data != nullptr && length > 0)
    {
        int first = GetFirstK(data, length, k, 0, length - 1);
        int last = GetLastK(data, length, k, 0, length - 1);

        if (first > -1 && last > -1)
            count = last - first + 1;
    }
    return count;
}

Sujet 2: Chiffres manquants dans 0 ~ n-1

Tous les nombres dans un tableau croissant de longueur n-1 sont uniques, et chaque nombre est dans la plage 0 ~ n-1, et il n'y a qu'un seul nombre parmi les n nombres dans la plage qui ne sont pas dans le tableau , Veuillez trouver ce numéro

Analyse du problème:
Méthode 1:
Nous pouvons d'abord calculer la somme de tous les nombres de 0 à n-1 en s1, puis calculer la somme de tous les nombres du tableau en s2, et la différence entre s1-s2 est 0 ~ n-1 Le numéro manquant.
Mais cette méthode n'est pas bonne, car la règle d'augmentation du tableau donnée dans la question n'est pas utilisée, et sa complexité temporelle est O (n)

Méthode 2:
nous pouvons utiliser l'idée de recherche binaire pour résoudre
car ces nombres 0 ~ n-1 sont triés dans le tableau, donc le début de ces nombres est le même que l'index du tableau, en supposant que le nombre m est le nombre manquant dans le tableau, Ensuite, le nombre après m et l'indice ne sont pas la relation correspondante,
Insérez la description de l'image ici
donc ce problème est transformé en trouver le premier élément dans le tableau trié qui n'est pas égal à l'indice

1. Si la valeur de l'élément du milieu et de l'indice sont égales, il suffit alors de rechercher la partie droite au tour suivant
2. Si la valeur de l'élément du milieu et de l'indice n'est pas égale

  1. Et l'élément devant lui n'est pas égal à son indice, alors l'élément est l'élément manquant
  2. Et l'élément en face de lui n'est pas égal à son indice, ce qui signifie que nous n'avons qu'à chercher à droite pour le prochain tour de recherche

En résumé, l'implémentation du code est la suivante:

int GetMissingNumbers(const int* numbers, int length)
{
    if (numbers == nullptr || length <= 0)
        return -1;

    int left = 0;
    int right = length - 1;
    
    while (left <= right)
    {
        int mid = (left + length) / 2;
        if (numbers[mid] != mid)
        {
            if (numbers[mid - 1] == mid - 1 || mid == 0)
                return mid;
            else
                right = mid - 1;
        }
        else
            left = mid + 1;
    }
    //缺失的是最后一个数字
    if (left == length)
        return length;

    return -1;
}

Thème 3: Éléments avec des valeurs égales et des indices dans le tableau

Supposons que chaque élément d'un tableau à augmentation monotone soit un entier et unique. Veuillez programmer une fonction pour trouver tout élément du tableau dont la valeur est égale à son indice. Par exemple, dans le tableau {-3, -1, 1, 3, 5}, le nombre 3 est égal à son indice.

Analyse du problème:
toujours utiliser pleinement la loi des tableaux croissants, en supposant que la valeur du i-ème nombre est supérieure à l'indice i, alors les nombres à sa droite sont supérieurs à l'indice correspondant. La prochaine ronde de recherche n'a besoin que de rechercher le nombre à sa gauche.
En supposant que la valeur du i-ème nombre est inférieure à l'indice i, alors les nombres à sa gauche sont plus petits que l'éditeur correspondant. La prochaine ronde de recherche n'a qu'à rechercher parmi les chiffres à sa droite.
Sur la base de la déclaration ci-dessus, le code est implémenté comme suit:

int GetNumberSameAsIndex( int* numbers, int length)
{
    if (numbers == nullptr || length <= 0)
        return -1;

    int left = 0;
    int right = length - 1;

    while (left <= right)
    {
        int mid = (right - left ) / 2 + left;
        if (numbers[mid] = mid)
            return mid;
        if (numbers[mid] < mid)
            left = mid + 1;
        else
            right = mid + 1;
    }
    return -1;
}
Publié 98 articles originaux · a gagné les éloges 9 · vues 3654

Je suppose que tu aimes

Origine blog.csdn.net/qq_43412060/article/details/105338437
conseillé
Classement