[Problema de lista vinculada] O problema de Joseph da lista circular unida

Prefácio

Atualize as postagens de escovação na forma de tópicos especiais. Bem-vindo a aprender a escovar comigo. Acredite em mim, sua persistência certamente trará ganhos inesperados. Cada pergunta fornecerá uma resposta simples, se você tiver uma abordagem mais elegante, bem-vindo para fornecer orientações, obrigado

[Descrição do tópico]

[Problema de lista vinculada] O problema de Joseph da lista circular unida

【Afirmação】

Entrada: o nó principal de uma lista circular unida individualmente e o número relatado m.

Retorno: O último nó sobrevivente, e este nó forma uma lista circular unida por si só, e todos os outros nós são excluídos.

【Dificuldade】

Táxi: ★ ☆☆☆

【responda】

Método 1: a complexidade do tempo é O (n * m)

Este problema é bastante simples se você não considerar a complexidade do tempo. Basta percorrer a lista ligada circular e excluir um nó toda vez que m nós forem percorridos. É suficiente saber que há apenas um nó restante na lista ligada.

código mostrado abaixo

 1    //时间复杂度为O(n*m)的解决方法
 2    public static Node josephusKill(Node head, int m) {
 3        if(head == null || m < 1)
 4            return head;
 5        Node last = head;
 6        //定位到最后一个节点
 7        while (head.next != last) {
 8            head = head.next;
 9        }
10        int count = 0;
11        while (head.next != head) {
12            if (++count == m) {
13                head.next = head.next.next;
14                count = 0;
15            } else {
16                head = head.next;
17            }
18        }
19        return head;
20    }

Como alguns telefones celulares podem ter caracteres truncados, postarei fotos aqui:

[Problema de lista vinculada] O problema de Joseph da lista circular unida
A complexidade de tempo desse método é O (n * m). A complexidade do tempo é usada como uma solução abaixo.

Método 2: a complexidade do tempo é O (n)

A dificuldade deste método é:

Escola: ★★★ ☆

Podemos numerar os nós da lista ligada circular. Se o número de nós na lista ligada for n, comece com o nó principal e numerar sequencialmente os nós, ou seja, o nó principal é 1, o próximo nó é 2 e o último nó é n.

Usamos f (n) para denotar que quando o comprimento da lista ligada circular é n, o número de sobreviventes é f (n). Obviamente, quando n = 1, f (n) = 1. Se pudermos encontrar a relação entre f (n) ef (n-1), podemos resolvê-la de forma recursiva. Presumimos que o número de pessoas seja n, e aqueles que se reportarem a m cometerão suicídio. Então o número inicial é

m - 2

m - 1

m

m + 1

m + 2

Após uma exclusão, o nó numerado m é excluído. Após a exclusão, restam apenas n-1 nós. A relação de conversão do número antes e depois da exclusão é:

Antes de deletar --- Depois de deletar

… ---…

m - 2 --- n - 2

m - 1 --- n - 1

m ---- Nenhum (porque o número foi excluído)

m + 1 --- 1 (porque contarei a partir daqui na próxima vez)

m + 2 ---- 2

… ----…

Existem apenas n-1 nós no novo anel. E os nós numerados m + 1, m + 2, m + 3 tornam-se os nós numerados 1, 2, 3 no novo anel.

Assumindo que antigo é o número do nó antes da exclusão e novo é o número após a exclusão de um nó, a relação entre o antigo e o novo é antigo = (novo + m-1)% n + 1.

Nota: Algumas pessoas podem se perguntar por que não é antigo = (novo + m)% n? Principalmente porque a numeração começa em 1, não em 0. Se new + m == n, o resultado final do cálculo será old = 0. Tão antigo = (novo + m-1)% n + 1.

Dessa forma, obtemos a relação entre f (n) ef (n-1), ef (1) = 1. Portanto, podemos fazer isso de forma recursiva.

código mostrado como abaixo:

 1   //时间复杂度为O(n)
 2    public static Node josephusKill2(Node head, int m) {
 3        if(head == null || m < 1)
 4            return head;
 5        int n = 1;//统计一共有多少个节点
 6        Node last = head;
 7        while (last.next != head) {
 8            n++;
 9            last = last.next;
10        }
11        //直接用递归算出目的编号
12        int des = f(n, m);
13        //把目的节点取出来
14        while (--des != 0) {
15            head = head.next;
16        }
17        head.next = head;
18        return head;
19    }
20
21    private static int f(int n, int m) {
22        if (n == 1) {
23            return 1;
24        }
25        return (f(n - 1, m) + m - 1) % n + 1;
26    }

Código da imagem:

[Problema de lista vinculada] O problema de Joseph da lista circular unida

Expansão do problema

Para a pergunta anterior, suponha que seja para deletar o número do nó K? Como resolver isso?

responda

Backstage responder, responder 3, obter resposta

Passado

[Problema de lista vinculada] Exclua o nó intermediário de uma lista unicamente vinculada

[Problema de lista vinculada] Como reverter elegantemente uma lista unida individualmente

[Problema de lista vinculada] Exclua o nó K na lista unicamente vinculada

[Combate de algoritmo] Gerar uma matriz de valores máximos de janela
[Problema de lista vinculada] O problema de Joseph da lista circular unida

Acho que você gosta

Origin blog.51cto.com/15015171/2555344
Recomendado
Clasificación