3
votes

Utilisation de la recherche binaire pour trouver toutes les occurrences d'un nombre dans un tableau trié en utilisant Javascript

J'ai récemment commencé à apprendre les algorithmes en JavaScript. J'expérimentais la recherche binaire lorsque je suis tombé sur cette question et j'ai essayé de l'implémenter, mais j'ai toujours des difficultés. La fonction prend deux paramètres (un tableau trié et un nombre) et renvoie un objet contenant l'occurrence et le nombre du nombre . L ' occurrence que j'obtiens n'est pas la bonne occurrence du nombre, et le count est constant.

Voici ce que j'ai fait jusqu'à présent: p >

function binarySearchOccurrence(array, element) {
    //declare the start index on the left side to zero
      let startIndex = 0;

      //declare the end index on the right side to the length of array minus 1
      let endIndex = array.length - 1;

      //set initial count to zero
      let count = 0;
      let occurrence = 0;

      //declare an empty object to hold the result of search and count 
      const result = {}

      //Applying binary search, iterate while start does not meed end
     while(startIndex <= endIndex){
          //find the middile index
          let middle = Math.floor((startIndex + endIndex)/2); 
              let guessElement = array[middle];
              count++;
              //if element is present in the middle, increment occurence
          if(guessElement === element){
                  occurrence++;

            while(startIndex <= endIndex){

                if(guessElement > element){
                    endIndex = middle - 1;
                    occurrence++;
                    break;

                } else {
                    startIndex = middle + 1;
                    occurrence++;
                    break;
                } 
            } 

              //Else look in the left or right side accordingly
          } else if (guessElement > element) {
                  endIndex = middle - 1;

          } else {
                  startIndex = middle + 1;
          }
      }
          result.occurrence = occurrence;
          result.count = count;
          return result;
  } 

lorsque je teste avec un tableau comme celui-ci: binarySearchOccurrence ([1, 2, 3, 4, 4, 4, 5, 5, 5, 6, 7, 8 , 9], 5) il renvoie {occurrence: 6, count: 4} au lieu de {occurrence: 3, count: 2} ; p >


7 commentaires

Qu'entendez-vous par count et occurrence ? À quoi ressemblent une occurrence et un count corrects pour votre exemple?


Je ne comprends pas pourquoi c'est si complexe. Il semble que vous commencez au milieu et recherchez les deux côtés de l'objet. Pourquoi ne pas commencer au début de l'objet (0) et rechercher jusqu'à ce que vous ayez atteint la fin (array.length -1)?


@lurker Je l'ai modifié.


@Sablefoste J'utilise la méthode de recherche binaire avec une complexité temporelle de O (logn).


Donc, occurrence est le nombre qu'il trouve. Qu'est-ce donc que count ?


Je suppose que je ne comprends toujours pas de quelle méthode vous parlez. Ce que je vois, c'est un second while (startIndex <= endIndex) { redondant intégré dans un while (startIndex <= endIndex) { identique. Donc, il fait tout deux fois. C'est peut-être pour cela que vos résultats sont le double des résultats escomptés.


@lurker count est le nombre de fois où mes boucles s'exécutent pour trouver le nombre. depuis que j'utilise la recherche binaire, cela devrait être moins.


3 Réponses :


0
votes

Votre code répète le décompte pour chaque occurrence.

Supposons que nous ayons un tableau [5,5,5,5], 5. Commençant par 0,3 comme début, fin. Milieu = 1 donc l'occurrence deviendra 1 (d'abord si) puis à l'intérieur de la boucle while, L'autre partie sera calculée pour que l'occurrence devienne 2. maintenant vous commencez par 2,3 donc mid est 2 qui est à nouveau compté par la première instruction if.

Autre approche:

  • Créez une fonction de recherche binaire qui renvoie la position de l'élément. Courir la première fois jusqu'à ce que vous trouviez mi dire x;
  • réexécutez-le de 0 à x-1 et x + 1 jusqu'à la fin
  • Faites ceci jusqu'à ce qu'il n'y ait pas de résultat pour la première moitié de la recherche et seconde moitié de la recherche
  • Les derniers résultats connus des recherches peuvent être soustrait pour compter le nombre d'occurrences.

Exemple pour mon approche.

[1, 2, 3, 4, 4, 4, 4, 4, 4, 5, 6, 7, 8]

binarysearch = bs (arr, val, start, end) = renvoie la position de val dans le tableau else -1

pos=bs(arr,val,start,end)
a=pos-1
ppos_a=a
while a!=-1 and a-1>=0:
    ppos_a=a
    a=bs(arr,val,0,a-1)

b=pos+1
ppos_b=b
while b!=-1 and b+1<=len-1:
    ppos_b=b
    b=bs(arr,val,b+1,len-1)

result = ppos_b-ppos_a

Cela devrait vous donner le décompte. Je doute un peu de la complexité mais cela semble être c log n où c


3 commentaires

J'aimerais que vous puissiez exprimer vos idées en utilisant du code, peut-être que je comprendrais mieux.


J'ajouterai une explication appropriée à mon approche dans la réponse, j'espère que vous pourrez alors écrire le code, mais je ne pense pas que cela réponde à votre exigence de log n. Ce serait un x log n, pas sûr de la complexité exacte cependant.


OKayy @kartikay



0
votes

Essayez d'utiliser ceci mais la complexité ne sera pas O (n) dans ce cas, un BST qui permet à l'un des enfants droit ou gauche d'être égal au nœud racine, nécessitera des étapes de calcul supplémentaires pour terminer une recherche où des nœuds dupliqués sont autorisés. Les clés en double sont-elles autorisées dans la définition de la recherche binaire arbres?

function binarySearchOccurrence(array, element) {

      //declare the start index on the left side to zero
      let startIndex = 0;

      //declare the end index on the right side to the length of array minus 1
      let endIndex = array.length - 1;

      //set initial count to zero
      let count = 0;
      let occurrence = 0;

      //declare an empty object to hold the result of search and count 
      const result = {}

      //Applying binary search, iterate while start does not meed end
      while (startIndex <= endIndex) {

        //find the middile index
        let middle = Math.floor((startIndex + endIndex) / 2);
        let guessElement = array[middle];
        count++;

        //if element is present in the middle, increment occurence
        if (guessElement > element) {
          endIndex = middle - 1;
          occurrence++;
        } else if (guessElement < element) {
          startIndex = middle + 1;
          occurrence++;
        } else if (guessElement === element) {
         occurrence++;
         count++;

         let searchleft = middle; // searchleft == middile index

         let searchright = middle;// searchright == middile index


//loop while we donot fine integar < element on left and integar > element on rigth;
          while (array[searchright] == guessElement && array[searchleft] == guessElement ) { 


            if (array[searchright] == element) { //if integar right still equal to element 
              searchright = searchright - 1;
              count++;
              occurrence++;
            } else if(array[searchleft] == element) { //if integar left still equal to element 
            searchleft = searchleft + 1;
              count++;
              occurrence++;
            }
          }
        }
        result.occurrence = occurrence;
        result.count = count;
        return result;
      }}

      console.log(binarySearchOccurrence([1, 2, 3, 4, 4, 4, 5, 5, 5, 6, 7, 8, 9], 5));


2 commentaires

votre code s'exécute mais l ' occurrence est incorrecte. il devrait renvoyer 2 au lieu de 3


@Dan il revient 2



0
votes

Cette question est une suggestion dans la barre latérale, alors que je cherchais une autre question, alors j'ai pensé à l'essayer.

Je ne suis pas un bon programmeur JavaScript de base, mais j'ai légèrement modifié votre code et je pense que le code ci-dessous donne vous corrigez le résultat

{occurence: 4, count: 8}

Sortie dans ma console

function binarySearchOccurrence(array, element, flag) {
            //declare the start
            //index on the left side to zero 
            let startIndex = 0; //declare the end index on
            // the right side to the length of array minus 1 
            let endIndex = array.length - 1;
            //set initial count to zero 
            let count = 0;
            let occurence = -1;
            const result = {}
            //Applying binary search, iterate while start does not meed end 
            while (startIndex <= endIndex) { //find the middle index 
                let middle = Math.floor((startIndex + endIndex) / 2);
                count++; //if element is
                //   present in the middle, increment occurence 
                if (array[middle] == element) {
                    occurence = middle;
                    if (flag == "last") {
                        startIndex = middle + 1;
                    } else {
                        endIndex = middle - 1;
                    }
                } else {
                    if (arr[middle] > element) {
                        endIndex = middle - 1;
                    } else {
                        startIndex = middle + 1;
                    }
                }
            }
            result.occurence = occurence;
            result.count = count;
            return result;
        }

        function countOccurence(arr, key) {
            let count = binarySearchOccurrence(arr, key, "last").count + binarySearchOccurrence(arr, key, "first").count;
            let occurence = (binarySearchOccurrence(arr, key, "last").occurence - binarySearchOccurrence(arr, key,
                "first").occurence) + 1;
            let result = {};
            result.occurence = occurence;
            result.count = count;
            return result;
        }
        let arr = [0, 1, 2, 3, 4, 4, 4, 4, 5, 6, 7, 8, 9];
        console.log(countOccurence(arr, 4));

Tout bon programmeur JS pourrait éditer et apporter des améliorations à ce code, Je l'apprécierai.


0 commentaires