Todos os desafios
Médio 0 resolvidos 0% de aceitação

Ordem de conclusão de tarefas paralelas

Execute tarefas concorrentemente com no máximo k por vez e informe a ordem em que elas terminam.

O que você vai aprender

  • Executar tarefas com limite de paralelismo
  • Simular o tempo com uma fila de prioridade
  • Desempatar tarefas que terminam juntas

Problema

Ver original (inglês)

Com async/await você pode iniciar várias tarefas e deixá-las executar ao mesmo tempo. Um SemaphoreSlim frequentemente limita quantas executam ao mesmo tempo.

Tarefas numeradas de 0 a n − 1 levam durations[i] unidades de tempo. No tempo 0, inicie o máximo de tarefas que o limite permitir, em ordem de índice. Sempre que tarefas terminarem, registre-as (se várias terminarem no mesmo instante, menor índice primeiro) e imediatamente inicie as próximas tarefas aguardando, em ordem de índice, para preencher os slots livres.

Implemente parallel_task_order(durations, limit).

Input

durations: Quanto tempo cada tarefa leva.

limit: O número máximo de tarefas executando ao mesmo tempo.

Output

Retorne os índices das tarefas na ordem em que elas terminam.

Restrições

1 ≤ n ≤ 100,000

1 ≤ durations[i] ≤ 10^6; 1 ≤ limit ≤ n

Exemplos

Exemplo 1
Entrada:
limit = 2
durations = [4, 2, 3, 1]

Saída esperada:
expected = [1, 0, 2, 3]
Entrada:
long long limit = 2;
std::vector<long long> durations = {4, 2, 3, 1};

Saída esperada:
std::vector<long long> expected = {1, 0, 2, 3};
Entrada:
long limit = 2;
long[] durations = new long[] {4, 2, 3, 1};

Saída esperada:
long[] expected = new long[] {1, 0, 2, 3};

Explicação

As tarefas 0 e 1 começam. A tarefa 1 termina em 2 e a tarefa 2 começa (termina em 5). A tarefa 0 termina em 4 e a tarefa 3 começa (termina em 5). As tarefas 2 e 3 terminam juntas, menor índice primeiro: [1, 0, 2, 3].

Exemplo 2
Entrada:
limit = 3
durations = [3, 1, 2]

Saída esperada:
expected = [1, 2, 0]
Entrada:
long long limit = 3;
std::vector<long long> durations = {3, 1, 2};

Saída esperada:
std::vector<long long> expected = {1, 2, 0};
Entrada:
long limit = 3;
long[] durations = new long[] {3, 1, 2};

Saída esperada:
long[] expected = new long[] {1, 2, 0};

Explicação

Todas as tarefas executam ao mesmo tempo e terminam em 1, 2 e 3: [1, 2, 0].

Como abordar

Tente sozinho primeiro e depois abra uma dica de cada vez.

Dica 1

Mantenha as tarefas em execução ordenadas pelo horário de término e depois pelo índice.

Dica 2

A cada passo, pule para o próximo horário de término e colete todas as tarefas que terminam nele.

Dica 3

Preencha as vagas livres com as próximas tarefas em espera, por índice.

Complexidade esperada

tempo O(n log limit), espaço extra O(limit)

Referências

Este desafio foi adaptado para o CodeUtility. Siga o enunciado e as restrições acima.

Aprenda com outros

Soluções da comunidade

Ainda não há soluções publicadas. Resolva este desafio para compartilhar a primeira.