Acerca de varios problemas de clasificación y problemas relacionados (actualización continua)

Problema de clasificación

Uno: clasificación de burbujas
1. La clasificación de burbujas es O (n ^ 2) complejidad de tiempo, y la complejidad de espacio adicional es O (1)
2. Pensamiento de burbujas: encuentre un valor máximo cada vez y colóquelo en la última posición , Y la próxima vez que lo busque de nuevo, ignore la última posición y luego coloque el segundo valor más grande en la penúltima posición, y así sucesivamente, cuando solo quede un número, no hay necesidad de volver a clasificar.
3. Ideas de programación burbujeante: la primera capa de bucle establece el punto final de la clasificación, y luego disminuye a la posición de 1 en secuencia, porque el proceso de comparación involucra dos posiciones, por lo que el punto final y el punto de inicio no necesitan coincidir, puede comparar y completar De hecho, el punto de partida no necesita ir al punto final, siempre y cuando llegue a la posición del punto final -1, ya se ha comparado. , El segundo ciclo es de 0 a menos que el punto final establecido por la primera capa, no es necesario que coincida con el punto final. El valor máximo antes de la posición final se intercambia a la posición final.
4. Código:

 public static void bubbleSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            //如果数组为空或者只要一个,就不用排序
            return ;
        }
        for (int end = arr.length - 1; end > 0; end--) {//end表示从后往前开始的排序好的数字
            for (int i = 0; i < end; i++) {//由于这是基于前一个数字,比较后一个数字,所以end所在位置的数字
                //是最后也要用于比较的,所以不需要担心,end=arr.length-1的时候,最后一个位置无法比较的情况。
                if (arr[i] > arr[i + 1]) {//当第i个数比i+1大,就交换,目的就是将最大的数字,往后一直排
                    swap(arr,i,i+1);
                }
            }
        }
    }

    public static void swap(int[] arr, int i, int j) {//交换数组内的数
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;

    }

Dos: ordenación por selección
1. La complejidad temporal de la ordenación por selección es O (n ^ 2), la complejidad del espacio extra es O (1)
2. La idea de la ordenación por selección: encuentra el valor mínimo cada vez y colócalo en la primera posición, Luego comience desde la segunda posición, el segundo valor mínimo se coloca en la segunda posición, y así sucesivamente, y el último valor se coloca en su propia posición
3. La idea de programación de la clasificación: similar al burbujeo, la primera Bucle de capa, que aumenta de 0 a la penúltima posición (cuando solo quedan dos números, suponiendo que el primer número es el valor mínimo, entonces habrá recorrido la última posición, y el penúltimo número y Se compara el último, por lo que no hay necesidad de ir al final, cuando solo queda un número, debe ser el valor mínimo entre los números restantes, porque solo existe. En el bucle anterior, podemos garantizar que Todos los valores anteriores son más pequeños que él . En el bucle de primer nivel, se supone que la posición inicial es el valor mínimo. El bucle de segundo nivel comienza desde la posición inicial establecida por el bucle de primer nivel y desciende hasta el último número, siempre que sea menor que la suposición. El valor mínimo de es Cambiar (en la posición inicial), y después hasta el final.
4. Código:

  public static void selectionSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return ;
        }//数组为空或者只有一个数字,直接返回

        for (int i = 0; i < arr.length - 1; i++) {//排序位置从0开始,代表已排好的,直到最后一个
           //i作为起始位置,如果直接在最后一个位置arr[arr.length-1]中出现,那么j=i+1就会越界,因为我们
            //是从i的下一个位置开始找所有的数字和最小的进行比较
            int minIndex=i;//假设第一个位置的数字是最小的
            for (int j = i + 1; j < arr.length; j++) {//初始的时候,由于假设了第一个是最小的,所以就
                //不存在遗漏了第一个的情况,可以直接从i+1开始
                minIndex=arr[j]<arr[minIndex]?j:minIndex;
                //当前值arr[j]是否小于最小值,如果小,就返回当前值的下标,否则不变
            }
            swap(arr, i, minIndex);
        }
    }

    public static void swap(int[] arr, int i, int j) {//数组内交换数字
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }

Tres: clasificación de inserción
1. La complejidad temporal de la clasificación de inserción involucra la mejor complejidad temporal, la peor complejidad temporal y la complejidad temporal promedio. En comparación con las dos primeras clases, la complejidad temporal fija es O (n ^ 2 ), Si la matriz ya está ordenada, el algoritmo de ordenación por inserción es O (n), si está completamente invertido, es O (n ^ 2). La complejidad del espacio adicional es O (1)
2. La idea de ordenación por inserción: similar a la ordenación Tarjeta, si solo tengo una tarjeta, entonces ya está ordenada ( expanda la posición ordenada hasta todas ), por lo que cuando se toma una nueva tarjeta, hay dos posibilidades , más pequeña que la primera tarjeta, o mayor o igual que, si Si es más grande o igual a la primera carta, ponla en tu mano (en la matriz) y continúa mirando la siguiente carta de la pila caótica. Por lo tanto, no hay un número mayor delante de ella , así que cambie la posición de la primera carta y la segunda carta, continúe mirando la tercera carta y así sucesivamente hasta el final
3. Ideas de programación: mirar la primera carta Para la última carta, se necesita un bucle para obtener una carta, Y delante de los números de comparar, no sólo que la primera carta, una tarjeta en lugar de en la parte delantera de lo que es pequeño hasta el momento, por lo que dos ciclos, el primer ciclo: desde 1 a la última carta. ( Para comprender el significado de cada variable, las variables en el primer ciclo son las tarjetas que deben compararse con las tarjetas ordenadas, por lo que solo hay una tarjeta en la primera tarjeta, no hay necesidad de comparar ) El segundo ciclo, porque La posición i-ésima necesita ser comparada, luego la posición i-1 debe ser el primer número que se compara con i, si necesita continuar, entonces i-1 entonces-, por lo que el segundo ciclo está representado por j i-1, entonces mientras j esté en la matriz y el número de j posiciones sea mayor que i, continúe con
4. Código:

 /*思想:如果我只有一张牌,那么它就是排好序的,所以第一个牌不用管,然后拿下一个
     * 数字和第一个牌比较,如果比第一个小,就交换,如果大就直接走到下一个位置,接下
     * 来就是普遍情况,也就是,这个位置的数字要和已经排序好的数字的最后的数字进行比较,
     * 如果大,就不管,如果小,就要一直交换到它在已经排序好的位置的前一个数比他小,为止*/
    public static void insertionSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return ;
        }//数组为空或者只有一个,就不需要排了
        for (int i = 1; i < arr.length; i++) {//0位置只有一张牌,所以
            //不需要排序,然后已经排序好的位置要走到最后一个位置才结束;
            /*i位置表示即将排序的位置,j表示与i进行比较的位置,这个j从i的前一个
            * 一直到0位置,我们的目的是i比j大,才可以,所以,一旦j比i大,就交换i和j位置的数字
            * 此时,j位置的数字,就是我们要排序的位置的数字,也就是原来的i,所以,再
            * j--,让j位置继续表示要和要排序的位置进行比较的位置。当j=0时,如果i仍然
            * 比j要小,那么交换,然后j无法递减,从而结束*/
            for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
                //其中之所以用j+1表示i,就是因为要排序的位置,可能会一直变,所以
                //需要用j+1表示,方便j递减的时候,让j+1一直表示将要排序的位置
                swap(arr,j,j+1);
            }

        }
    }

    public static void swap(int[] arr, int i, int j) {
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }

Cuatro: combinación de clasificación
1. combinación de clasificación: la complejidad temporal es O (n * logn), la complejidad de espacio adicional es O (n) (para eflujo)
2. La idea de la combinación de clasificación: si desea ordenar una matriz, coloque Esta matriz se divide en dos. Si se ordenan tanto la izquierda como la derecha, entonces solo necesita organizar las dos matrices en una fila externa , que es organizar las dos matrices ordenadas en una matriz ordenada. El ordenamiento por fusión es un buen uso de las partes ya ordenadas. Está hecho. La comparación entre cada dato se puede usar de manera eficiente
3. La idea de programación del ordenamiento por fusión: usamos la palabra "si", es decir, si alguien Para organizar la izquierda y la derecha para nosotros, solo necesitamos fusionar las dos matrices ordenadas, pero el problema es que nadie nos ayuda a convertir las dos matrices secundarias en una matriz ordenada , pero nuestro propio propósito no es cambiar esta matriz grande ¿Es una matriz ordenada? Por lo tanto, creo que puede usar la recursividad ( siempre que pueda usar la recursividad, puede usar un bucle para resolver, no es más que empujar la pila usted mismo, este problema se discutirá en otros artículos en el futuro ), si continuamos dividiendo la matriz, eventualmente dividiremos la matriz. Cada número se convierte en una matriz separada. Si la matriz tiene solo un número, no hay necesidad de ordenar, por lo que la condición de retorno establecida es si el punto de inicio de la clasificación == punto final, luego regresa directamente , luego se resuelve el proceso de división Ahora, el punto es cómo fusionar las dos matrices ordenadas en una. Primero, usamos la matriz de ayuda. Este número debería acomodar todos los números de las dos matrices. ¿Si es así? En primer lugar, debemos saber que nm significa la diferencia entre los dos. Esta diferencia es a menudo el número de [m, n) o (m, n] de m a n, pero lo que queremos es [m, n] Es decir, necesitamos ambas posiciones, por lo que el tamaño de esta matriz de ayuda es: R-L + 1A continuación, establezca dos punteros para que apunten a dos matrices, desde cero hasta la última posición, compare constantemente los dos valores puntiagudos, quien sea pequeño, colocamos quién en la matriz de ayuda, lo que también significa El número señalado no tiene sentido, por lo que ++ apunta al siguiente número, pero el número señalado por otro puntero no se ha puesto en práctica, por lo que todavía tiene sentido y continúa comparando. Al final, debe haber un puntero que cruce el límite, lo que significa dos Una de las "matrices" se ha eliminado por completo, entonces solo necesitamos poner todas las otras matrices en la ayuda, porque es obvio que todos los valores restantes son mayores que los anteriores. Finalmente, debido a que asumimos las dos matrices, de hecho, las dos matrices son solo un fragmento en el medio de la matriz grande, por lo que necesitamos ayuda para cubrir todo el fragmento , entonces, ¿cómo cubrirlo? La matriz de ayuda es de cero a help.length-1, la matriz original hemos interceptado los fragmentos de L a R, entonces solo necesitamos la matriz original de L + 0 a L + arr.length-1 posición, solo cubra con ayuda, Eso es todo , esto es para encontrar la conexión entre las dos matrices
4. Código:

  //归并的开头,用于检验是否需要排序
    public static void mergeSort(int[] arr) {
        if (arr.length < 2 || arr == null) {
            return ;
        }
        sortProcess(arr, 0, arr.length - 1);
    }

    public static void sortProcess(int[] arr, int L, int R) {
        //当起点等于终点的时候,意味着不需要继续分,已经排序号了
        if (L == R) {
            return ;
        }
        /*
        * 在数组很大的时候,那么L+R很有可能越界,会超过这个类型承载的限度,所以需要修改*/
//        int mid = (L + R)/2;//找到这次排序的中点位置
        int mid=L+(R-L)/2;
        sortProcess(arr, L, mid);//排序左边
        sortProcess(arr, mid + 1, R);//排序右边
        merge(arr,L,mid,R);
    }

    public static void merge(int[] arr, int L,int mid, int R) {
        int[] help=new int[R-L+1];//由于传的值是左闭,右闭的[L,R],
        //但是R-L则是有一个闭合,有一个开,例如2~4,4-2=2,但是[2,4]
        //有三个数字,所以,当两个值都是闭合的,那么就要+1;
        //所以此时help数组,正好存储[L,R],那么只需要将help填满,然后再
        //覆盖到原数组即可
        int i=0;//表示help数组的指针
        int p1=L;//表示左边起点
        int p2=mid+1;//表示右边起点
        while(p1<=mid && p2<=R){//当两个都没有越界的时候,
            help[i++]=arr[p1]<arr[p2]? arr[p1++] :arr[p2++];
            /*help数组i位置的值,等于左,右较小的值,选中了哪边,那边的指针
            * 就要++,方便下次比较*/
        }
        //两个指针必有一个最终会越界,哪个越界了,我们将剩下那部分的余下全部
        //copy到help中
        while (p1 <= mid) {
            help[i++] = arr[p1++];
        }
        while (p2 <= R) {
            help[i++]=arr[p2++];
        }
        //至此,help数组填写完成,接下来,要将这部分,覆盖到原
        //数组的L~R部分
        for (int j = 0; j < help.length; j++) {
            arr[L+j]=help[j];
            /*精髓在于,help数组与arr差异在于,要开始的位置,
            * 恰好和arr数组相差L,也就是说,L+j,且j=0,正好对应arr[L]
            * 的位置,所以找到这两个数组的联系,就很好解决这段代码*/
        }
    }

Cinco (1): problema de la bandera nacional holandesa (Manual de clasificación rápida)
1. Abstracción del problema: divida un grupo de números en tres partes, con m como límite, más pequeño que m a la izquierda, tan grande como m en el medio, que m El grande está en el lado derecho
2. Idea de resolución de problemas: divida la matriz en tres partes, menos que la región, igual a la región y mayor que la región, y luego expanda gradualmente estas tres partes hasta la matriz completa
3. Idea de programación: Primero, divida cada región, Todas las posiciones de la matriz completa son áreas para dividir , por lo que la posición anterior de la matriz es menor que la posición inicial del área, y el lado derecho de la última posición de la matriz es mayor que la posición del comienzo del área, entonces, ¿es igual al área? Coloque el área igual en el lado derecho del área menor que (actualmente vacía) y luego empuje el área igual hacia adelante. Con las ideas anteriores, comience a escribir código, defina el área, necesite la identificación del puntero, por lo que la identificación es menor que el área p1 y mayor que el área p2, en cuanto al área, ya que puede presionarse por menos que el área, luego puede usar uno menos y luego usar un puntero i , Atraviese el área a dividir , si es mayor que el valor estándar, mayor que el área –1, luego intercambie el valor de la posición p2 con ella y luego continúe viendo la relación entre el valor de la posición de i y el valor estándar ; si el valor es menor que el valor dividido, menor que el área ++ , Y luego intercambie el valor de la posición p1 con ella. En este momento, el valor menor que el área todavía se garantiza que sea menor que el valor estándar, y el valor de la posición señalada por i en este momentoDebe haber sido atravesado Imagine un proceso en el que la posición de i se refiere al lado derecho del área menor al principio, por lo que si el valor señalado por i es pequeño, entonces el proceso de intercambio es equivalente a menos del área anexada hacia adelante Posición, si no es ++, entonces el área que se dividirá se superpondrá con el área menor que, por lo que se requiere ++. Si es igual al valor estándar, i ++, cuando se encuentra de nuevo con menos que el valor estándar, tenga en cuenta: i y menor que Solo hay un valor de área igual en el medio del área, es decir, el valor equivalente se intercambiará a la posición i durante el intercambio, por lo que la posición i todavía está dividida, es decir, el proceso de empujar el área igual al área es menor ; por lo tanto, la posición i debe ++, porque después de que se completa el intercambio, el valor señalado por i es en realidad menor o igual que el área, que ya se ha dividido; entonces, ¿a dónde voy? Si llega al final de la matriz, será caótico, porque después de encontrar un área mayor que, el valor es mayor que el valor estándar, por lo que el área mayor se expande, pero porque el lado izquierdo del área mayor ha estado cerca del área igual o menor que el área, una vez mayor La expansión del área hará que el proceso de intercambio sea caótico, así que iré al frente del área
4. Código:

  public static int[] flag(int[] arr, int L, int R, int num) {
         int less=L-1;//小于区域在需要判断的区域的左侧
         int more=R+1;//大于区域在需要判断的区域的右侧
         int index=L;//待定区域的指针
        while (index <more) {//指针走遍待定区域,重点是待定区域,如果走遍右侧,那么会把划分过的大于区域搞乱
            //index<=R是错误的
            if (arr[index] < num) {//当前值小于num
                swap(arr, ++less, index++);//将这个值与小于区域的后一个数字交换
            } else if (arr[index] > num) {//当前值大于num
                swap(arr,--more,index);//将这个值和大于区域的前一个数交换,
                //但是此时不清楚被交换的是什么数字,所以index不动
            }else {//当前值==num,则忽略,
                index++;
                //本质上,这是小于区域,推动着等于区域前进。
            }

        }
        return new int[]{less + 1, more - 1};  //返回等于区域的第一个值和最后一个值
        //当没有等于区域的时候,第一个值会大于第二个值,所以无效
    }

    public static void swap(int[] arr, int i, int j) {
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }

Cinco (2): clasificación rápida
1. Complejidad de tiempo de clasificación rápida: la expectativa a largo plazo es O (n * logN) la complejidad de espacio adicional (clasificación rápida aleatoria) es O (logN) porque cada punto de interrupción es una dicotomía, luego dicotomía Todas las veces que haya puntos de interrupción
2. La idea de una clasificación rápida: con el problema de la bandera holandesa como antecedente, entendemos el proceso de partición (después de la división, qué hace), luego está inacabado, continuará
seis (1) Prerrequisitos del conocimiento de la ordenación del montón
1. Árbol binario completo y árbol binario completo
2. Representación de la matriz del árbol binario completo
3. Concepto del
montón 4. El poder del montón (por ejemplo)
Seis (2): Clasificación del montón
Siete: Clasificación del cubo (la clasificación no se basa en la comparación) , Principalmente para dar un ejemplo)

Resumen: Puntos de conocimiento involucrados
1. Cognición recursiva
2. Logaritmo
3. Problema de suma pequeña
4. Problema de número ordinal inverso
5 Clasificación integral en ingeniería
6. Comparador
7. Conocimiento aleatorio

Publicado 12 artículos originales · elogiado 0 · visitas 138

Supongo que te gusta

Origin blog.csdn.net/weixin_44065691/article/details/105546528
Recomendado
Clasificación