web-dev-qa-db-fra.com

Recherche de la valeur maximale dans un tableau à l'aide de la récursivité

Pour l'une des questions que l'on m'a demandé de résoudre, j'ai trouvé la valeur maximale d'un tableau à l'aide d'une boucle for, j'ai donc essayé de le trouver à l'aide de la récursivité et voici ce que j'ai proposé:

public static int findMax(int[] a, int head, int last) {

    int max = 0;
    if (head == last) {
        return a[head];
    } else if (a[head] < a[last]) {
        return findMax(a, head + 1, last);
    } else {
        return a[head];
    }
}

Donc, cela fonctionne bien et obtient la valeur maximale, mais ma question est la suivante: est-il correct d’avoir pour le cas de base un retour [tête] et pour le cas où la valeur à la tête est> la dernière valeur?

8
Scarl

Vous pouvez tout aussi facilement le faire avec un seul compteur, juste l'index de la valeur que vous voulez comparer cette fois:

public static int findMax(int[] a, int index) {
    if (index > 0) {
        return Math.max(a[index], findMax(a, index-1))
    } else {
        return a[0];
    }
}

Cela montre beaucoup mieux ce qui se passe et utilise la disposition par défaut "récursivité", par exemple. avec un pas de base commun. L'appel initial est en faisant findMax(a, a.length-1).

14
Joost

C'est en fait beaucoup plus simple que cela. Le cas de base est si vous avez atteint la fin du tableau (la partie "else" du bloc de contrôle ternaire ci-dessous). Sinon, vous renvoyez le maximum de l'appel en cours et de l'appel récursif.

public static int findMax(int[] a) {
    return findMax(a, 0);
}
private static int findMax(int[] a, int i) {
    return i < a.length
           ? Math.max(a[i], findMax(a, i + 1))
           : Integer.MIN_VALUE;
}

À chaque élément, vous retournez le plus grand de l'élément actuel et tous les éléments avec un plus grand index. Integer.MIN_VALUE sera retourné uniquement sur des tableaux vides. Cela se passe dans le temps linéaire.

7
azz

Je résoudrais ceci en divisant le tableau en deux lors de chaque appel récursif.

 findMax(int[] data, int a, int b)

où a et b sont des indices de tableau.

La condition d'arrêt est quand b - a <= 1, alors ce sont des voisins et le max est max (a, b);

L'appel initial:

 findMax(int[] data, int 0, data.length -1);

Cela réduit la profondeur de récursivité maximale de N à log2 (N).
Mais l’effort de recherche reste toujours O (N).

Cela se traduirait par 

int findMax(int[] data, int a, int b) {
   if (b - a <= 1) {
     return Math.max(data[a], data[b]);
   } else {
     int mid = (a+b) /2; // this can overflow for values near Integer.Max: can be solved by a + (b-a) / 2; 
     int leftMax =  findMax(a, mid);
     int rightMax = findMax(mid +1, b);
     return Math.max(leftMax, rightMax);
   }
}
2
AlexWien
class Test
{
    int high;
    int arr[];
    int n;
    Test()
    {
        n=5;
        arr = new int[n];
        arr[0] = 10;
        arr[1] = 20;
        arr[2] = 30;
        arr[3] = 40;
        arr[4] = 50;
        high = arr[0];
    }
    public static void main(String[] args)
    {
       Test t = new Test();
       t.findHigh(0);
       t.printHigh();
    }
    public void printHigh()
    {
        System.out.println("highest = "+high);
    }
    public void findHigh(int i)
    {
        if(i > n-1)
        {
            return;
        }
        if(arr[i] > high)
        {
            high = arr[i];
        }
        findHigh(i+1);
        return;
    }
}
1

Je suis tombé sur ce fil et cela m'a beaucoup aidé. Ci-joint, mon code complet dans les cas de récursivité et de division/conquête. Le temps d’exécution de divide & conquer est légèrement meilleur que la récursivité. 

//use divide and conquer.
public int findMaxDivideConquer(int[] arr){
    return findMaxDivideConquerHelper(arr, 0, arr.length-1);
}
private int findMaxDivideConquerHelper(int[] arr, int start, int end){
    //base case
    if(end - start  <=  1) return Math.max(arr[start], arr[end]);
    //divide
    int mid = start + ( end - start )/2;
    int leftMax =findMaxDivideConquerHelper(arr, start, mid);
    int rightMax =findMaxDivideConquerHelper(arr, mid+1, end);
    //conquer
    return Math.max( leftMax, rightMax );
}

// use recursion. return the max of the current and recursive call
public int findMaxRec(int[] arr){
    return findMaxRec(arr, 0);
}
private int findMaxRec(int[] arr, int i){
    if (i == arr.length) {
        return Integer.MIN_VALUE;
    }
    return Math.max(arr[i], findMaxRec(arr, i+1));
}
1
rrr

Je sais que c'est un vieux fil, mais peut-être que ça aide!

public static int max(int[] a, int n) {
        if(n < 0) {
            return Integer.MIN_VALUE;
        }
        return Math.max(a[n-1], max(a, n - 2));

    }
1
user6694478

Qu'en est-il de celui-ci?

public static int maxElement(int[] a, int index, int max) {
    int largest = max;
    while (index < a.length-1) {
        //If current is the first element then override largest
        if (index == 0) {
            largest = a[0];
        }
        if (largest < a[index+1]) {
            largest = a[index+1];
            System.out.println("New Largest : " + largest); //Just to track the change in largest value
        }
        maxElement(a,index+1,largest);
    }
    return largest;
}
1
Recomer

Solution optimisée

public class Test1 {
    public static int findMax(int[] a, int head, int last) {

        int max = 0, max1 = 0;

        if (head == last) {
            return a[head];

        } else if (a[head] < a[last]) {
            max = findMax(a, head + 1, last);
        } else
            max = findMax(a, head, last - 1);

        if (max >= max1) {
            max1 = max;
        }
        return max1;


    }

    public static void main(String[] args) {
        int arr[] = {1001, 0, 2, 1002, 2500, 3, 1000, 7, 5, 100};
        int i = findMax(arr, 0, 9);
        System.out.println(i);
    }
}
0
Mani Jaiswal

Vous pouvez le faire de manière récursive comme suit.

Relation récurrente c'est quelque chose comme ça.

   f(a,n)   = a[n]   if n == size
            = f(a,n+1) if n != size

La mise en œuvre est la suivante.

   private static int getMaxRecursive(int[] arr,int pos) {
         if(pos == (arr.length-1)) {
                return arr[pos];
         } else {           
                return Math.max(arr[pos], getMaxRecursive(arr, pos+1));
         }
   }

et appel va ressembler à ceci

      int maxElement = getMaxRecursive(arr,0);
0
Vallabh Patade

ce n'est pas correct! votre code ne trouvera pas l'élément maximum dans le tableau, il retournera uniquement l'élément qui a une valeur supérieure à celle des éléments adjacents, pour résoudre ce problème, l'élément de valeur maximum dans l'intervalle peut être passé comme argument pour la méthode récursive.

    private static int findMax(int[] a, int head, int last,int max) {
    if(last == head) {
        return max;
    }
    else if (a[head] > a[last]) {
            max = a[head];
            return findMax(a, head, last - 1, max);
        } else {
            max = a[last];
            return findMax(a, head + 1, last, max);
        }
}
0
Learnaholic
  public int GetMax(int [] A, int index)  {

         index += 1;
         if (index >= A.Length) return 0;
         return Math.Max(A[index], GetMax(A, index + 1));

     }
0
Khaled Saleh