Divida e conquiste exercícios de estratégia para design e análise de algoritmos (on)

Divida e conquiste estratégia para resolver o problema um: pesquisar pela metade

Descrição do Problema

Dado que n elementos a [0: n-1] foram classificados em ordem crescente, agora precisamos encontrar um elemento x específico entre esses n elementos.

analise de problemas

Comece a pesquisar a partir do meio do elemento e continue pesquisando por x reduzindo pela metade, e os subproblemas para pesquisar pela metade são independentes uns dos outros.

Implementação de algoritmo

//折半查找递归实现
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
}

Divida e conquiste estratégia para resolver o problema dois: aplicativo de tecnologia de pesquisa binária um

Descrição do Problema

Dado um número de inteiros, pergunte se a soma de um par de números é igual ao número fornecido.
Entrada:
4
2 5 1 4
6
Saída
1 5
Explicação: Se houver vários pares de números que atendem aos requisitos, produza o par com o menor número

analise de problemas

  • Classifique a matriz do pequeno ao grande primeiro
  • Use a pesquisa binária para encontrar um valor correspondente ao anterior
  • Pare de pesquisar quando for encontrado, caso contrário, continue

Implementação de algoritmo

//折半查找递归实现
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;
        }
    }
}

Divida e conquiste estratégia para resolver o problema três: aplicativo de tecnologia de pesquisa binária dois

Descrição do Problema

Insira n números, produza-os do pequeno para o grande e produza os números repetidos apenas uma vez.
Entrada:
5
2 4 4 5 1
Saída:
1 2 4 5

analise de problemas

A maneira mais fácil é usar o conjunto, usar a natureza do conjunto, aqui não usamos esse método, usando a tecnologia de pesquisa binária

  • Primeiro, classifique a matriz de pequena a grande
  • Começando pelo número do meio, registre a primeira e a última ocorrência do número, respectivamente
  • Analise a subsequência à esquerda da mesma maneira
  • Envie o número
  • Analise a subsequência certa da mesma maneira

Implementação de algoritmo

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);
}

Divida e conquiste estratégia para resolver o problema quatro: modo e multiplicidade

Descrição do Problema

Para um determinado conjunto de números múltiplos S consistindo em n números naturais, programe para calcular o modo e a multiplicidade de S

analise de problemas

  • Use armazenamento de array
  • Classifique a matriz primeiro
  • Registre o índice do número do meio, o número de ocorrências do número do meio e a posição da primeira ocorrência do número do meio
  • Compare a multiplicidade do número intermediário com a multiplicidade do registro anterior, se for maior que a multiplicidade do registro anterior, atualize num e some
  • Se a maior multiplicidade for menor que o número de dígitos à direita do número do meio, então a análise recursiva à direita
  • Se a maior multiplicidade for menor que o número de dígitos à esquerda do número do meio, analise recursivamente à esquerda

Implementação de algoritmo

#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);
    }
}

Divida e conquiste estratégia para resolver o problema cinco: fusão de intervalo

Descrição do Problema

  Dados n intervalos fechados [ai; bi], onde i = 1,2, ..., n. Quaisquer dois intervalos fechados adjacentes ou que se cruzam podem ser mesclados em um intervalo fechado. Por exemplo, [1; 2] e [2; 3] podem ser combinados em [1; 3], [1; 3] e [2; 4] podem ser combinados em [1; 4], que é [1; 2] e [ 3; 4] Não é possível mesclar.
  Determine se esses intervalos podem ser finalmente mesclados em um intervalo fechado; em caso afirmativo, imprima o intervalo fechado; caso contrário, imprima no.

analise de problemas

  • Definir estrutura de intervalo para armazenamento e definir função de comparação
  • Depois de classificar os grupos de intervalo de entrada, divida e conquiste nos lados esquerdo e direito até que seja reduzido ao problema de fusão entre as duas comunidades
  • Se não puder ser combinado, o programa gera não e sai diretamente
  • Se possível, mescle os resultados após dividir e conquistar para obter o intervalo final

Implementação de algoritmo

#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 outros artigos neste blog

Divida e conquiste estratégia para design e análise de algoritmos

Projeto de algoritmo e análise de exercícios de algoritmo recursivo (parte 2)

Projeto de algoritmo e análise de exercícios de algoritmo recursivo (on)

Problema de triângulo digital no projeto e análise de algoritmos

Projeto de algoritmo e análise de ZOJ2104- Let the Balloon Rise

Projeto de algoritmo e análise de fila de prioridade e solução ZOJ1167

Acho que você gosta

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