Ejercicios de estrategia de dividir y conquistar para el diseño y análisis de algoritmos
- Divide y conquista la estrategia para resolver el problema uno: busca por la mitad
- Divide y conquista la estrategia para resolver el problema dos: aplicación de tecnología de búsqueda binaria uno
- Estrategia de dividir y conquistar para resolver el problema tres: aplicación de tecnología de búsqueda binaria dos
- Divide y conquista la estrategia para resolver el problema cuatro: modo y multiplicidad
- Estrategia de dividir y conquistar para resolver el problema cinco: fusión de intervalos
- Recomendado por otros artículos de este blog
Divide y conquista la estrategia para resolver el problema uno: busca por la mitad
Descripción del problema
Dado que n elementos a [0: n-1] se han clasificado en orden ascendente, ahora necesitamos encontrar un elemento específico x entre estos n elementos.
análisis del problema
Empiece a buscar desde el medio del elemento y busque x dividiendo a la mitad continuamente, y los subproblemas para buscar a la mitad son independientes entre sí.
Implementación de algoritmos
//折半查找递归实现
int binarySearch(int a[],int left,int right,int x){
if(left<=right){
int middle = (left + right) / 2;
if(x == a[middle]) return middle;
else if(x < a[middle]) return binarySearch(a,left,middle-1,x);
else return binarySearch(a,middle+1,right,x);
}
return -1; //没找到返回-1
}
Divide y conquista la estrategia para resolver el problema dos: aplicación de tecnología de búsqueda binaria uno
Descripción del problema
Dado un número de enteros, pregunte si la suma de un par de números es igual al número dado.
Entrada:
4
2 5 1 4
6
Salida
1 5
Explicación: Si hay varios pares de números que cumplen los requisitos, envíe el par con el número más pequeño
análisis del problema
- Ordene la matriz de pequeña a grande primero
- Utilice la búsqueda binaria para encontrar un valor correspondiente al primero
- Deje de buscar cuando lo encuentre, de lo contrario continúe
Implementación de algoritmos
//折半查找递归实现
int binarySearch(int a[],int left,int right,int x){
if(left<=right){
int middle = (left + right) / 2;
if(x == a[middle]) return middle;
else if(x < a[middle]) return binarySearch(a,left,middle-1,x);
else return binarySearch(a,middle+1,right,x);
}
return -1; //没找到返回-1
}
void SumNumberSearch(int a[],int length,int sum){
for(int i=0;i<length;i++){
if(binarySearch(a,i+1,length-1,sum-a[i])){
cout<<a[i]<<" "<<sum-a[i];
break;
}
}
}
Estrategia de dividir y conquistar para resolver el problema tres: aplicación de tecnología de búsqueda binaria dos
Descripción del problema
Ingrese n números, envíelos de pequeño a grande y envíe los números repetidos solo una vez.
Entrada:
5
2 4 4 5 1
Salida:
1 2 4 5
análisis del problema
La forma más fácil es usar set, aprovechar la naturaleza del set, aquí no usamos este método, usando tecnología de búsqueda binaria
- Primero ordena la matriz de pequeña a grande
- Comenzando por el número del medio, registre la primera y última aparición del número respectivamente
- Analice la subsecuencia de la izquierda de la misma manera
- Salida del número
- Analice la subsecuencia correcta de la misma manera
Implementación de algoritmos
void lineSearch(int a[],int left,int right){
int number,middle,l,r,i;
if(left>right) return;
middle = (left + right)/2;
number = a[middle];
i = middle - 1;
while(a[i]==number && i>=left) i--;
l = i;
i = middle + 1;
while(a[i]==number && i<=right) i++;
r = i;
lineSearch(a,left,l);
cout<<number<<" ";
lineSearch(a,r,right);
}
Divide y conquista la estrategia para resolver el problema cuatro: modo y multiplicidad
Descripción del problema
Para un conjunto de números múltiples dado S que consta de n números naturales, programe para calcular la moda y la multiplicidad de S
análisis del problema
- Usar almacenamiento de matriz
- Ordene la matriz primero
- Registre el índice del número del medio, el número de apariciones del número del medio y la posición de la primera aparición del número del medio.
- Compare la multiplicidad del número intermedio con la multiplicidad del registro anterior, si es mayor que la multiplicidad del registro anterior, actualice num y sum
- Si la mayor multiplicidad es menor que el número de dígitos a la derecha del número del medio, entonces el análisis recursivo a la derecha
- Si la mayor multiplicidad es menor que el número de dígitos a la izquierda del número del medio, entonces analice recursivamente a la izquierda
Implementación de algoritmos
#include <iostream>
#include <algorithm>
#define N 100
using namespace std;
int num = 0; //存储众数
int sum = 0; //存储重数
/*
统计中间数出现的数量
*/
int count(int[],int,int);
/*
找到中间数第一次出现的位置
*/
int start(int[],int,int);
/*
找众数和其重数
*/
void modeAndMultiplicity(int[],int,int);
int main()
{
int a[N],n;
cout<<"请输入数组元素数量:";
cin>>n;
cout<<"请输入数组元素:";
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
modeAndMultiplicity(a,0,n-1);
cout<<"众数"<<num<<"的重数为"<<sum<<endl;
return 0;
}
/*
统计中间数出现的数量 实现
*/
int count(int a[],int front,int rear){
int i = 0; //计数器
int mid = a[(front+rear)/2];
for(int j=front;j<=rear;j++){
if(a[j] == mid){
i++;
}
}
return i;
}
/*
找到中间数第一次出现的位置 实现
*/
int start(int a[],int front,int rear){
int x = 0;
int mid = a[(front+rear)/2];
for(int i=front;i <= rear;i++){
if(a[i] == mid){
x = i;
break;
}
}
return x;
}
/*
找众数和其重数 实现
*/
void modeAndMultiplicity(int a[],int front,int rear){
int mNum = (front+rear)/2; //当前中间数的下标
int mSum = count(a,front,rear); //当前中间数的重数
int mLeft = start(a,front,rear); //当前中间数第一次出现的位置
if(mSum > sum) {
//重数大则替换众数和其重数
sum = mSum;
num = a[mNum];
}
if(rear-(mLeft+mSum)+1 > sum){
//右边数量大于重数 则向右找
modeAndMultiplicity(a,mLeft+mSum,rear);
}
if(mLeft > sum){
//左边数量大于重数 则向左找
modeAndMultiplicity(a,front,mLeft-1);
}
}
Estrategia de dividir y conquistar para resolver el problema cinco: fusión de intervalos
Descripción del problema
Dados n intervalos cerrados [ai; bi], donde i = 1,2, ..., n. Dos intervalos cerrados adyacentes o que se cruzan se pueden fusionar en un intervalo cerrado. Por ejemplo, [1; 2] y [2; 3] se pueden combinar en [1; 3], [1; 3] y [2; 4] se pueden combinar en [1; 4], que es [1; 2] y [ 3; 4] No se puede fusionar.
Juzgue si estos intervalos se pueden fusionar finalmente en un intervalo cerrado, si es así, emita el intervalo cerrado, de lo contrario la salida no.
análisis del problema
- Definir la estructura de intervalos para el almacenamiento y definir la función de comparación
- Después de ordenar los grupos de intervalos de entrada, divida y conquiste en los lados izquierdo y derecho hasta que se reduzca al problema de fusión entre las dos comunidades
- Si no se puede combinar, el programa emite no y sale directamente
- Si es posible, combine los resultados después de dividir y conquistar para obtener el intervalo final
Implementación de algoritmos
#include <iostream>
#include <algorithm>
//定义区间数量
#define N 100
using namespace std;
//定义区间结构体
struct Interval{
int left,right;
};
//定义区间比较函数
bool compareInterval(Interval,Interval);
//区间合并
Interval intervalMerge(Interval[],int,int);
int main()
{
Interval interval[N];
int n;
cout<<"请输入区间数量:";
cin>>n;
for(int i=0;i<n;i++)
cin>>interval[i].left>>interval[i].right;
sort(interval,interval+n,compareInterval);
Interval tempInterval = intervalMerge(interval,0,n-1);
cout<<tempInterval.left<<" "<<tempInterval.right<<endl;
return 0;
}
bool compareInterval(Interval mLeft,Interval mRight){
if(mLeft.left < mRight.left)
return true;
return false;
}
Interval intervalMerge(Interval internal[],int left,int right){
if(left == right)
return internal[left];
Interval tempInterval1 = intervalMerge(internal,left,(left+right)/2),
tempInterval2 = intervalMerge(internal,(left+right)/2+1,right);
if(tempInterval1.right >= tempInterval2.left){
//符合合并条件 进行合并
Interval tempInterval;
tempInterval.left = tempInterval1.left;
tempInterval.right = tempInterval1.right>=tempInterval2.right
?tempInterval1.right
:tempInterval2.right;
return tempInterval;
}else{
//否则退出
cout<<"no"<<endl;
exit(0);
}
}
Recomendado por otros artículos de este blog
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)
Problema del triángulo digital en el diseño y análisis de algoritmos
Diseño y análisis de algoritmos de ZOJ2104- Let the Balloon Rise
Diseño y análisis de algoritmos de cola de prioridad y solución ZOJ1167