El algoritmo es hermoso (dos) --- recursividad

Recursividad

  • Encuentra duplicaciones: descubre los subproblemas y descompone continuamente la pregunta original en subproblemas.
  • Buscar cambios: descubra qué cambios se han realizado entre el problema original y los subproblemas
  • Encuentre el límite: encuentre el punto de salida recursiva, no el bucle infinito

Parte 1: Conceptos básicos de recursividad

  • Encontrar de forma recursiva la jerarquía de un número
public class Hello {
    
    //求某个数的阶层
    public static int ff1(int n){
    
    
        if(n==0)
            return 1;
        return n * ff1(n-1);
    }
    public static void main(String[] args) {
    
    
        System.out.println(ff1(3));
    }
}
  • Imprime el valor de i a j
public class Hello {
    
    //打印i到j的值
    public static void ff1(int i,int j){
    
    
        if(i==j)
            return;
        System.out.println(i);
        ff1(i+1,j);
    }
    public static void main(String[] args) {
    
    
        ff1(3,9);
    }
}
  • Suma de matriz
public class Hello {
    
    //数组求和
    public static int ff1(int arr[], int i){
    
    
        if (i==arr.length-1)
            return arr[arr.length-1];
        return arr[i] + ff1(arr,i+1);
    }
    public static void main(String[] args) {
    
    
        int arr[] = {
    
    1,2,3,4,5,6,7,8,9,10}; //自定义了一个数组
        int i = 0;

        System.out.println(ff1(arr, i));
    }
}
  • Cuerda inversa
public class Hello {
    
    //翻转字符串
    public static String ff1(String str, int j){
    
    
        if (j==0){
    
    
            return str.charAt(j)+"";
        }
        return str.charAt(j)+ff1(str,j-1);
    }
    public static void main(String[] args) {
    
    
        String str1 = "abcdefg";
        String str2 = "i love you";
        System.out.println(ff1(str1,str1.length()-1));
        System.out.println(ff1(str2,str2.length()-1));
    }
}
  • secuencia Fibonacci
  • O (2 ^ n), este tipo de similitud también tiene el n-ésimo orden de 3,8 (problema de ocho reinas)
  • ¿Por qué esta complejidad temporal?
  • Debido a que cada recursividad se divide en dos partes nuevas, y las partes nuevas deben calcularse, 1, 2, 4, 8 ...
public class Hello {
    
    //递归完成斐波拉契数列
    public static int ff1(int j){
    
    
        if(j==2||j==1)
            return 1;
        return ff1(j-1)+ff1(j-2);
    }
    public static void main(String[] args) {
    
    
        System.out.println(ff1(5));
    }
}
  • Máximo común divisor
  • orden log (n) (derivado de la fórmula matemática, aproximadamente cada dos veces, n se reduce a la mitad)
  • ¿Por qué esta complejidad temporal?
m n
n m%n (根据数学推导 m%n < m/2)
m%n n%(m%n) (根据数学推导 n%(m%n) < n/2)
也就是说每隔两个数就衰减一半,
	
次数 规模
2次 n/2
4次 n/2^2
6次 n/2^3
...
k次 n/2^(k/2)

再取对数...
故与log(n)阶类似。
public class Hello {
    
    //最大公约数
    public static int ff1(int m, int n){
    
    
        if (m%n == 0)
            return n;
        else
            return ff1(n, m%n); //辗转相除法
    } 
    public static void main(String[] args) {
    
    
        System.out.println(ff1(4,3)); //控制m比n大就好了
    }
}
  • Recursividad de cambio de ordenación por inserción
  • o (n ^ 2): Imagine que el ordenamiento por inserción es más o menos similar al burbujeo. Requiere que un elemento se compare con los elementos restantes uno por uno, y se usa un elemento cada vez, lo que equivale a dos bucles for.
public class Hello {
    
    //插入排序改递归
    public static void ff1(int arr[], int k){
    
    
        if (k==0){
    
    
            return;
        }
        ff1(arr,k-1); //将前k-1个元素进行排序
        int x = arr[k];
        int index = k-1;
        while (x<arr[index]){
    
    
            arr[index+1] = arr[index]; // 比k大的元素应该后移
            index--;
            if(index==-1)
                break;
        }
        arr[index+1] = x;
    }
    public static void main(String[] args) {
    
    
        int arr [] = {
    
    3,6,2,8,4,9};
        ff1(arr, arr.length-1);
        for(int i = 0;i<arr.length;i++){
    
    
            System.out.print(arr[i]);
        }
    }
}
  • Torre de Hanoi
  • O (2 ^ n)
  • Se encuentra que cada vez que se llama a la función, es el doble que la llamada anterior, que es similar a la secuencia de Fibonacci.
public class Hello {
    
    //汉诺塔问题
    public static void hanno(int N, String A, String B, String C){
    
    
        if (N==1){
    
    
            System.out.println(N+"by"+A+"--->"+B);
        }else{
    
    
            hanno(N-1, A, C, B);
            System.out.println(N+"by"+A+"--->"+B);
            hanno(N-1,C, B, A);
        }
    }

    public static void main(String[] args) {
    
    
        hanno(6,"A", "B", "C");
    }
}
  • Búsqueda binaria
  • orden de registro (n)
  • ¿Por qué esta complejidad temporal?
  • Encuentre la mitad cada vez, entiéndalo como 2 ^ n (el número de veces que busca) = x (el número total de veces), y luego tome el logaritmo, que es el orden log (n)
public class Hello {
    
    //二分查找递归解法
    public static int ff1(int arr[], int l, int r, int key) {
    
    
         if (l > r)
            return -1;
         else if (key > arr[(l+r)/2])
            return ff1(arr, (l + r) / 2 + 1, r, key);
         else if(key < arr[(l+r)/2])
            return ff1(arr, l, (l + r) / 2, key);
         else
            return (l+r)/2;
    }
    public static void main(String[] args) {
    
    
        int array[] = {
    
    1,2,3,4,5,6};
        System.out.println(ff1(array,0,5,3));
    }
}
  • Tipo de colina
  • nlog (n) ~ n ^ 2
  • Los pocos y muchos elementos aquí se definen en función de la agrupación de clasificación Hill, no el número real de elementos.
  • Si los elementos ordenados son muy malos, es decir, cuando hay pocos elementos, están ordenados, y cuando hay muchos elementos, están desordenados, resultando en
  • ¿Por qué rápido? : Cuando hay pocos elementos, están desordenados, cuando hay muchos elementos, básicamente están en orden.
public class Hello {
    
    //希尔排序
    public static int[] ff1(int arr[]){
    
    
        for(int interval = arr.length/2; interval>0 ;interval/=2){
    
    //控制每一次的排序量
            for(int j = interval;j< arr.length; j++){
    
    
                int num = arr[j];
                int index = j-interval;
                while(j>-1&&num<arr[index]){
    
    
                    arr[index+interval] = arr[index];       //这就是插入排序, 与之前的插入排序是一样的
                    index -= interval;
                    if(index<0){
    
    
                        break;
                    }
                }
                arr[index+interval] = num;
            }
        }
        return arr;
    }
    public static void main(String[] args) {
    
    
        int array[] = {
    
    3,7,2,9,4,1};
        array = ff1(array);
        for(int i = 0;i< array.length;i++){
    
    
            System.out.println(array[i]);
        }
    }
}
  • Hill clasifica el estado menos favorito
    Inserte la descripción de la imagen aquí
  • Esto hace que la complejidad de tiempo de la clasificación de Hill sea O (n ^ 2), porque una gran parte de los elementos deben insertarse más tarde, más los recorridos anteriores, la complejidad de tiempo es O (n ^ 2)

  • Hill ordena el estado de favorito
    Inserte la descripción de la imagen aquí
  • Por supuesto, esto representa una parte de la situación, siempre que sea más o menos ordenado, se puede alcanzar este nivel (sustancialmente el orden se refiere al gran número de la derecha, y se supone que cada intercambio es como máximo una vez, es decir , cada vez es O (n ^ 2). El número está determinado por el número de elementos / 2, que es log (n), y la multiplicación de los dos es la complejidad de tiempo mínima.

La segunda parte, complejidad y estabilidad del algoritmo

  • Tabla de potencia de 2
    Inserte la descripción de la imagen aquí
  • Cómo evaluar la complejidad del algoritmo
    Inserte la descripción de la imagen aquí
  • Estabilidad del algoritmo de clasificación
    Inserte la descripción de la imagen aquí
    Inserte la descripción de la imagen aquí

La tercera parte, ejemplo recursivo

  • Pregunta 1: Xiaobai sube las escaleras (diseño recursivo)
  • Xiaobai va a subir las escaleras. Las escaleras tienen n escalones. Xiaobai puede subir 1, 2 o 3 escalones a la vez. Se implementa un método para calcular cuántos Xiaobai ha completado las escaleras.
  • Idea: Imagínese recorriendo el recorrido completo, retrocediendo un paso, un segundo paso y un tercer paso. En estos tres pasos, puede recorrer el recorrido completo en un paso, por lo que obtiene la fórmula de recurrencia: f (n) = f ( n-1) + f (n-2) + f (n-3), aquí se refiere a la suma del número de métodos, es la recursividad del número de métodos (es decir, la forma de caminar por las escaleras) , que es muy similar a la secuencia de Fibonacci, aquí La complejidad del tiempo del algoritmo es O (n ^ 3), y preste atención a controlar la salida, es decir, cuando n = 1, n = 2 y n = 3, deben ser controlado.
  • el código se muestra a continuación:
import java.util.Scanner;

public class Hello {
    
    //小白上楼梯 : 递归设计
    public static int ff1(int n){
    
    
        if (n==0) return 1;
        else if (n==1) return 1;
        else if (n==2) return 2; // 因为可能先走一步,再走一步, 或者直接走两步
        else
            return ff1(n-1) + ff1(n-2) + ff1(n-3);
    }

    public static void main(String[] args) {
    
    
        Scanner sc = new Scanner(System.in);
        while(true) {
    
    
            int num = sc.nextInt();
            int req = ff1(num);
            System.out.println(req);
        }
    }
}
  • Pregunta 2: Gire el número más pequeño de la matriz (reforma dicotomía)
  • Mover los primeros elementos de una matriz hasta el final de la matriz se denomina rotación de la matriz. Ingrese una rotación de una matriz ascendente y emita el elemento más pequeño de la matriz girada.
  • Idea: Descubrimos que el elemento más pequeño en la matriz rotada es la mitad que está desordenada después de que la matriz se biseca (para ver si está ordenada o desordenada, simplemente compare el tamaño del elemento al principio y al final de la matriz) , y el elemento más pequeño está de nuevo Siempre a la derecha del elemento más grande, es decir, cuando solo quedan dos elementos, el de la derecha es el elemento más pequeño
  • Tenga en cuenta que este método tiene grandes desventajas, como rotar la prueba de matriz 10111 para obtener la respuesta incorrecta, etc ... emm
  • el código se muestra a continuación:
import java.util.Scanner;

public class Hello {
    
    //旋转数组的最小元素
    public static void ff1(int arr[]){
    
    
       int begin = 0;
       int end = arr.length - 1;

       //应该没有这种特殊的旋转
       if (arr[begin]<arr[end]) System.out.println(arr[begin]);;

       while (true){
    
    
           int mid = (begin + end) / 2;
           if (arr[begin]<arr[mid]){
    
     //左边有序, 去右边找
               begin = mid;
           }else if(arr[mid]<arr[end]){
    
     //右边有序, 去左边找
               end = mid;
           }else if(begin+1==end){
    
    
               System.out.println(arr[end]);
               break;
           }
       }

    }

    public static void main(String[] args) {
    
    
        int arr[] = {
    
    2,3,4,0,1};
        ff1(arr);
    }
}

Supongo que te gusta

Origin blog.csdn.net/qq_45911278/article/details/112839244
Recomendado
Clasificación