Selección de tiempo lineal del diseño y análisis de algoritmos (C ++)

Algoritmo de selección de tiempo lineal

  • Imitando el algoritmo de clasificación rápida
  • Utilice la estrategia de dividir y conquistar en matrices

Ejemplo uno

Descripción del problema

Para una matriz dada de n elementos a [0: n-1], se requiere encontrar el k-ésimo elemento más pequeño de él

Entrada: introduzca varios conjuntos de casos de prueba.
 Hay 2 filas para cada caso de prueba. La
 primera fila son números enteros n y k (1≤k < n≤1000), y la
 segunda fila son n números enteros.

Salida: el k-ésimo elemento más pequeño

análisis del problema

Sabemos que la idea de una especie de algoritmo de clasificación rápida es:
 encontrar un número como estándar, poner el número más pequeño a la izquierda y el número más grande a la derecha

Para encontrar el k-ésimo elemento más pequeño, la forma más grosera es ordenarlos todos, pero esto ha hecho mucho trabajo adicional. Basándonos en la idea de ordenación única del algoritmo de ordenación rápida, podemos usar el primer elemento de la matriz como estándar y poner los más pequeños a la izquierda. Coloque más grande que el de la derecha:

  • Cuando el elemento en el lado izquierdo de este estándar y suman k, se encuentra el k-ésimo número más pequeño
  • Cuando el elemento a la izquierda de este estándar y suman menos que k, continúe hacia la derecha para encontrar el número más pequeño (k-1-subíndice del número)
  • Cuando el elemento a la izquierda de este estándar suma más que k, continúa hacia la izquierda para encontrar el k-ésimo número más pequeño

Implementación de algoritmos

#include <iostream>
#include <algorithm>
#define N 100
using namespace std;
//一维数组容器
int a[N];

//线性选择算法寻找第k小的元素
int linearTimeSelection(int,int,int);

int main()
{
    
    
    int n,k;
    cout<<"输入数组大小:";
    cin>>n;
    if(n>N || n<1) {
    
    
        cout<<"预留空间不足或数组大小非法!";
        exit(0);
    }

    cout<<"输入数组元素:";
    for(int i=0;i<n;i++) cin>>a[i];

    cout<<"查找第几小的元素:";
    cin>>k;
    if(k > n || k < 1){
    
    
        cout<<"查找位置非法!";
        exit(0);
    }
    cout<<linearTimeSelection(0,n-1,k);
    return 0;
}
/*
    left 进行线性选择的首位下标
    right 进行线性选择的末尾下标
    k 寻找第k位小的元素
*/
int linearTimeSelection(int left,int right,int k){
    
    
    if(left >= right) return a[left];
    int point = a[left];
    int i = left,
        j = right+1;

    while(1){
    
    
        do{
    
    i++;}while(a[i] < point);
        do{
    
    j--;}while(a[j] > point);
        if(i>=j) break;
        swap(a[i],a[j]);
    }

    if(j-left+1 == k) return point;
    a[left] = a[j];
    a[j] = point;

    if(j-left+1 < k) return linearTimeSelection(j+1,right,k-(j+1-left));	//向右找
    return linearTimeSelection(left,j-1,k);	//向左找
}

Ejemplo 2

Descripción del problema

  Una compañía petrolera planea construir un oleoducto principal de este a oeste. El oleoducto pasa por un campo petrolero con n pozos petroleros. De cada pozo de petróleo, debe haber un oleoducto conectado al oleoducto principal a lo largo del camino más corto (o al sur o al norte).
  Dada la ubicación de n pozos de petróleo, es decir, sus coordenadas x (este-oeste) y coordenadas y (sur-norte), el programa calcula la suma de la longitud mínima del oleoducto desde cada pozo de petróleo hasta el oleoducto principal.

Ingrese la
  primera línea es un número entero n, que indica el número de pozos de petróleo (1≤n≤10 000) Las
  siguientes n líneas son las posiciones de los pozos de petróleo, cada línea contiene dos números enteros xey (-10 000≤x, y≤10 000)
Salida de
  la suma de la longitud mínima del oleoducto desde cada pozo de petróleo hasta el oleoducto principal

Ejemplo de entrada
5
1 2
2 2
1 3
3 -2
3 3
Ejemplo de salida
6

Diagrama de muestra
Inserte la descripción de la imagen aquí

análisis del problema

  • ¿Cómo determinar la ubicación del oleoducto principal?
    A partir del diagrama de análisis que dibujé en la muestra de entrada anterior, se puede ver claramente que la tubería principal solo está determinada por la coordenada y, y la tubería principal existe en el rango del valor y (es decir, los valores máximo y mínimo de la coordenada y de entrada Entre), porque la distancia entre el pozo de petróleo y el oleoducto principal debe ser la mínima, por lo tanto, encuentre la mediana del valor y de la ubicación del pozo de petróleo .
  • ¿Cómo calcular la suma de distancia mínima?
    Después de encontrar la ubicación del oleoducto principal, calculamos la distancia al oleoducto principal para cada pozo de petróleo y las sumamos.
  • Con respecto al cálculo de la mediana
    1. Clasificación directa, encuentre el elemento con el subíndice n / 2;
    2. Use el algoritmo de selección de tiempo lineal para seleccionar el n / 2-ésimo elemento más pequeño; (usamos este método)

Implementación de algoritmos

#include <iostream>
#include <algorithm>
#define N 10000
using namespace std;

//存储油井的y值
int a[N];
//线性时间选择算法
int linearTimeSelection(int,int,int);
int main()
{
    
    
    int n,temp;
    cout<<"请输入油井的数量:";
    cin>>n;
    cout<<"请输入油井坐标:";
    for(int i=0;i<n;i++)
        cin>>temp>>a[i];
    //主管道位置
    int mid = linearTimeSelection(0,n-1,n/2);

    int sum = 0;
    for(int i=0;i<n;i++){
    
    
        sum += abs(a[i]-mid);
    }

    cout<<sum<<endl;
    return 0;
}

int linearTimeSelection(int left,int right,int k){
    
    
    if(left >= right) return a[left];
    int i = left,
        j = right+1;
    int point = a[left];

    while(1){
    
    
        do{
    
    i++;}while(a[i]<point);
        do{
    
    j--;}while(a[j]>point);
        if(i>=j) break;
        swap(a[i],a[j]);
    }

    if(j-left+1 == k) return point;
    a[left] = a[j];
    a[j] = point;

    if(j-left+1 < k) return linearTimeSelection(j+1,right,k-(j-left+1));
    return linearTimeSelection(left,j-1,k);
}

Recomendado por otros artículos de este blog

Ejercicios de estrategia de dividir y conquistar para el diseño y análisis de algoritmos (parte 2)

Ejercicios de estrategia de dividir y conquistar para el diseño y análisis de algoritmos (activado)

Estrategia de dividir y conquistar para el diseño y análisis de algoritmos

Diseño de algoritmos y análisis de ejercicios de algoritmos recursivos (abajo)

Diseño de algoritmos y análisis de ejercicios de algoritmos recursivos (encendido)

Supongo que te gusta

Origin blog.csdn.net/L333333333/article/details/102646289
Recomendado
Clasificación