[Algoritmo] Divida e conquiste em quatro etapas

O método de dividir e conquistar tem três etapas em cada nível de recursão:
1) Decomposição: Decompor o problema original em vários subproblemas menores e independentes com a mesma forma do problema original
2) Resolva: se o subproblema é menor em escala Resolva diretamente se for fácil de resolver, caso contrário, resolva cada subproblema recursivamente
3) Combine: Combine a solução de cada subproblema na solução do problema original.

Cena aplicável

Informações técnicas www.yehe.org

Quando o problema que se aplica a nós é um grande problema, e esse grande problema pode ser dividido em vários pequenos problemas.

Divida e conquiste quatro etapas

  1. Esclareça a estratégia de decomposição: esclareça a estratégia de decomposição do grande problema passo a passo até o pequeno problema final e, em seguida, precisamos esclarecer a função da função de acordo com a estratégia de decomposição .
    Por exemplo, se nossa estratégia de decomposição é meia decomposição, então nossa função precisa ter um domínio de intervalo para determinar o intervalo de decomposição; se for uma decomposição decrescente, então nossa função precisa ter uma contagem para registrar o resultado da decomposição decrescente.

    Por exemplo, o grande problema da classificação rápida pode ser decomposto em colocar n elementos na posição correta, e o grande problema da Torre de Hanói é colocar n discos na posição correta de baixo para cima.

  2. Procure o menor problema: o menor problema é a versão mais simplificada do grande problema, o estado inicial do problema e o menor subproblema é a saída.

  3. Resolva problemas menores: Use uma estratégia de decomposição para decompor os problemas principais em problemas secundários. O segundo menor problema é o problema entre o menor problema e o grande problema, que é ligeiramente maior do que o menor problema. Isso torna o segundo menor problema universal para resolver o grande problema, ou seja, a solução geral para o grande problema pode ser encontrado por meio do segundo menor problema. Obtenha uma solução para o próximo problema menor.

    Por exemplo, o segundo problema menor de classificação rápida é colocar um elemento na posição correta, e o segundo problema menor da Torre de Hanói é colocar um disco inferior na posição correta.

  4. Mesclar problemas menores: Isso é adicionado de acordo com as necessidades do problema.

1542615-20210119125206590-1139624038.png

Estratégia de decomposição clara

A primeira etapa é esclarecer como decompor o grande problema passo a passo no pequeno problema final e esclarecer qual é a função dessa função e o que ela deseja realizar.
Estratégia de decomposição: grande problema = n * pequeno problema. Se o grande problema for um array, o pequeno problema será um elemento do array.

Por exemplo, o grande problema do algoritmo de classificação rápida é classificar os n elementos no array e colocá-los na posição correta, então o pequeno problema de decomposição é colocar um elemento no array na posição correta.
O grande problema da Torre de Hanói é pegar emprestadas as n placas do pilar A e colocar o pilar B no pilar C de grande a pequeno, então o pequeno problema que se decompõe é pegar emprestado o fundo e a placa maior do A pilar para colocar B No pilar C.

E essa função é totalmente definida por você. Em outras palavras, não nos importamos qual é o código na função e como ele é escrito, mas primeiro devemos entender para que serve a sua função.

Por exemplo: Encontrar o valor máximo em uma matriz
Para resolver este problema, a
primeira etapa é esclarecer nossa estratégia de decomposição. Aqui, minha estratégia de decomposição é meia decomposição;
como a estratégia de decomposição é meia decomposição, então estamos prestes a escrever esta função deve especificar o intervalo de decomposição, caso contrário, não há como dividir a decomposição.

Estratégia de decomposição clara: grande problema = encontre o maior número de n elementos, dividido ao meio, pequeno problema = encontre o maior número a partir da comparação de dois elementos.

//找出一个数组中的最大值
// 明确分解策略:大问题=从n个元素中找到最大的数字并返回,折半分解,小问题=从2个元素比较大小找到最大数字并返回。
int f(int[] nums, int l, int r) {
    
}

Encontre o menor problema (condições iniciais)

Dividir para conquistar é decompor continuamente grandes problemas em problemas sub-pequenos no código interno de implementação de função e, em seguida, decompor pequenos problemas em problemas menores. Portanto, devemos encontrar a condição final de dividir para conquistar, ou seja, dado um limiar de decomposição, caso contrário, ele continuará a se decompor, indefinidamente.

1542615-20210119112735821-2088674292.png

  • Deve haver uma condição final clara. Porque há uma divisão e conquista "pontos" ter "e" , deve haver um ponto claro, até este ponto, não "quebrar" e iniciar "Mesclar".

Na segunda etapa , precisamos descobrir quando o valor do parâmetro e o grau de decomposição, divisão e conquista termina, e então retornar diretamente o resultado.
( Geralmente é a condição inicial e, em seguida, expanda passo a passo da condição inicial ao resultado final )

Nota: neste momento, devemos saber diretamente qual é o resultado da função com base no valor deste parâmetro.

Vamos continuar a melhorar a função máxima acima.
A segunda etapa é encontrar o problema mínimo:
quando l> = r, ou seja, há apenas um elemento restante, podemos saber diretamente que f (l) é o valor máximo ;
então, a saída recursiva é aquela quando l> = r, a função retorna f (l).
do seguinte modo:

// 明确分解策略:大问题=从n个元素中找到最大的数字并返回,折半分解,小问题=从2个元素比较大小找到最大数字并返回。
int f(int[] nums, int l, int r) {

      // 寻找最小问题:最小问题即是只有一个元素的时候
      if (l >= r) {
            return nums[l];
      }
}

Obviamente, quando l> = r, também sabemos quanto f (r) é igual a e f (r) também pode ser usado como uma saída recursiva. A saída de divisão e conquista pode não ser exclusiva.

Resolva pequenos problemas

Na terceira etapa , esclarecemos a estratégia de decomposição antes e agora é a hora de usá-la. Precisamos usar essa estratégia de decomposição para decompor grandes problemas em segundos pequenos. Dessa forma, ele pode ser decomposto no menor problema passo a passo e, em seguida, usado como uma saída de função.

  • Problema mínimo: decompor em apenas um elemento, l> = r, f (l) é o máximo
  • Estratégia de decomposição: meia decomposição, f (nums, l, r) → f (nums, l, (l + r) / 2), f (nums, (l + r) / 2 + 1, r)

Dividir e conquistar:

  • Pontos: F (nums, l, r) → f (nums, l, (l + r) / 2), f (nums, (l + r) / 2 + 1, r). Desta forma, o problema é reduzido de n para n / 2 , e precisamos apenas encontrar o valor máximo desses n / 2 elementos. Desta forma, lentamente "aponte" de f (n), f (n / 2) para f (1).
  • União: Desta forma, você pode " unificar " passo a passo de 1 a n / 2, n ...
// 明确分解策略:大问题=从n个元素中找到最大的数字并返回,折半分解,小问题=从2个元素比较大小找到最大数字并返回。
int f(int[] nums, int l, int r) {

      // 寻找最小问题:最小问题即是只有一个元素的时候
      if (l >= r) {
            return nums[l];
      }

      // 使用分解策略
      int lMax = f(nums, l, (l+r)/2);
      int rMax = f(nums, (l+r)/2+1, r);
}

Etapa 4: Resolva o problema menor.
Na etapa anterior, decompomos o grande problema no próximo problema menor, então, como resolver esse problema menor? Resolver esse problema menor também é uma solução para o problema da nossa próxima decomposição, portanto, não podemos ser descuidados.
A maneira de resolver o problema menor é comparar o tamanho dos dois problemas menores e obter o maior valor, o problema pode ser resolvido.

// 明确分解策略:大问题=从n个元素中找到最大的数字并返回,折半分解,小问题=从2个元素比较大小找到最大数字并返回。
int f(int[] nums, int l, int r) {

      // 寻找最小问题:最小问题即是只有一个元素的时候
      if (l >= r) {
            return nums[l];
      }

      // 使用分解策略
      int lMax = f(nums, l, (l+r)/2);
      int rMax = f(nums, (l+r)/2+1, r);

      // 解决次小问题:比较两个元素得到最大的数字
      return lMax > rMax ? lMax : rMax;
}

Mesclando questões menores

A fusão aqui é para resolver o segundo menor problema, ou seja, comparar dois elementos para obter o maior número.

Neste ponto, as cinco etapas de dividir e conquistar são concluídas, então a função dessa função de dividir e conquistar também é realizada.
Talvez os leitores iniciantes achem muito estranho, isso pode obter o valor máximo?
Então, vamos avançar passo a passo.
Assumindo que n é o número de elementos na matriz, f (n) é o valor máximo de n elementos,
f (1) tem apenas um elemento, você pode obter um certo valor
f (2) e comparar o valor de f ( 1), você também pode determinar o valor de
f (4) em comparação com f (2), e pode ser determinado
...
f (n / 2)
f (n) também pode ser determinado em comparação com f (n / 2 ). Você pode
ver se isso pode ser resolvido. Agora, n pode dividir e conquistar para obter o resultado!

Instância

Numero maximo

Encontre o maior número em uma matriz.

Estratégia de decomposição: meio a meio

Encontre o maior elemento de 1 a r.

// 明确分解策略:大问题=从n个元素中找到最大的数字并返回,折半分解,小问题=从2个元素比较大小找到最大数字并返回。
int f(int[] nums, int l, int r) {

      // 寻找最小问题:最小问题即是只有一个元素的时候
      if (l >= r) {
            return nums[l];
      }

      // 使用分解策略
      int lMax = f(nums, l, (l+r)/2);
      int rMax = f(nums, (l+r)/2+1, r);

      // 解决次小问题:比较两个元素得到最大的数字
      return lMax > rMax ? lMax : rMax;
}

Torre de Hanói

A lenda da Torre de Hanói

Torre de Hanói: O problema da Torre de Hanói (também conhecida como Torre de Hanói) é um brinquedo educacional derivado de uma antiga lenda indiana. Quando Brahma criou o mundo, ele fez três pilares de diamante Em um pilar, 64 discos de ouro foram empilhados em ordem de tamanho de baixo para cima. O Brahma ordenou que o Brahmin recolocasse o disco em outro pilar em ordem de tamanho de baixo. Também é estipulado que o disco não pode ser ampliado no disco pequeno e apenas um disco pode ser movido entre os três pilares de cada vez.

Se uma vez a cada segundo, quanto tempo leva? Demora mais de 584,554 bilhões de anos para mover essas peças de ouro, e estima-se que a expectativa de vida do sistema solar é de dezenas de bilhões de anos. Depois de 5845,54 bilhões de anos, toda a vida na terra, incluindo os pagodes e templos do Vaticano, há muito desapareceu.

Demonstração e análise do jogo Torre de Hanói:

1) Se houver um disco, A-> C

Se tivermos n> = 2, podemos sempre considerá- lo como dois discos 1. O disco inferior 2. O disco superior
2) O disco superior A-> B
3) O disco inferior A -> C
4) Troque todos os discos de Torre B de B-> C

Implementação do código da Torre de Hanói:

Veja a demonstração do código do professor:

package com.atguigu.dac;

public class Hanoitower {

    public static void main(String[] args) {
        hanoiTower(10, 'A', 'B', 'C');
    }
    
    //汉诺塔的移动的方法
    //使用分治算法
    // 明确分解策略:我们的问题是有n个盘子,可是如果是n个盘子的话我们不会分,不知道结果;如果盘子数量为1、2、3就好了,所以我们按盘子数依次减一分解
    public static void hanoiTower(int num, char a, char b, char c) {
        // 寻找最小问题:只有一个盘
        //如果只有一个盘
        if(num == 1) {
            System.out.println("第1个盘从 " + a + "->" + c);
        } else {
            // 解决次小问题:由于我们是按盘子数-1来进行分解的,所以次小问题是一个盘子和n-1个盘子的汉诺塔,将一个最下面的盘子摆放到正确的位置
            //如果我们有 n >= 2 情况,我们总是可以看做是两个盘 1.最下边的一个盘 2. 上面的所有盘
            //1. 先把 最上面的所有盘 A->B, 移动过程会使用到 c
            hanoiTower(num - 1, a, c, b);
            //2. 把最下边的盘 A->C
            System.out.println("第" + num + "个盘从 " + a + "->" + c);
            //3. 把B塔的所有盘 从 B->C , 移动过程使用到 a塔  
            hanoiTower(num - 1, b, a, c);
        }
    }
}

Acho que você gosta

Origin blog.csdn.net/weixin_48967543/article/details/115253836
Recomendado
Clasificación