Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Maurício Antunes
Maurício Antunes

Posted on

Resolvendo o "Five sort"

O objetivo desse post é demonstrar como eu pensei e solucionei o desafio citado usando uma técnica chamada two pointers.

Desafio

Dado um array de números inteiros, mova os números 5 para o final dele. Exemplo:[1, 5, 2, 5, 3]
Como resultado, espera-se o seguinte retorno da função:[1, 3, 2, 5, 5] ou[2, 1, 3, 5, 5]. O importante é que os 5 estejam no final do array.

Abordagem

Há várias maneiras de resolver esse problema. Muitas pessoas deram ótimas soluçõesnessa thread no Twitter.

Vou abordar nesse texto uma forma mais profunda de ver o problema além do código.

Uma das maneiras de abordar esse problema é removendo todos os 5 da lista original, adicioná-los em outros lista e concatenar no final (lista1 + lista2). Ou remover da lista e adicionar no final.

Não é uma solução ruim, porém, ela tem uma alta complexidade de tempo. Toda vez que você remove um item de um array e ele não é o último, o array precisa ser rearranjado. Isso significa que toda remoção vai adicionar N passos adicionais na sua solução.

Uma abordagem interessante pro problema é usar a técnica two pointers, assumindo que podemos modificar o array in-place, ou seja, modificar o valor do array que, em Python, por exemplo, é mutável.

A técnica se baseia em ter dois ponteiros para fazer comparações em diferentes partes do array, enquanto se move e aplica todas as operações necessárias para resolver o problema.

Nossa abordagem irá comparar os elementos do início com os do fim do array. Com um exemplo de dois elementos ([5, 1]) fica mais fácil. Começando o algoritmo, comparamos o primeiro valor com o último. O primeiro é 5, então movemos ele pro fim, trocando pelo 1, resultando em[1, 5].

Vamos adicionar dois valores[5, 5, 1, 3].
Primeiro e últimos trocam, pois o primeiro é 5. Movemos os dois ponteiros, trocando 5 e 1 também, resultando em[3, 1, 5, 5].

Abaixo uma demonstração visual (com texto alternativo) do problema sendo resolvido:

Na imagem temos dois ponteiros, i e j representados em verde e azul respectivamente. Na próxima parte, demonstramos um array com os valores 5, 5, 1, 3 e uma seta mostrando que 5 e 3 trocam de lugar. Na próxima linha, 3, 5, 1, 5, com uma seta mostrando que 5 e 1 trocam de lugar. No fim, o array correto com valores 3, 1, 5, 5

Nosso algoritmo se baseia em comparar os elementos do array em direção ao meio do dele. Enquanto o ponteiroi for menor que o ponteiroj, nós continuamos a comparar os elementos e trocando quando for necessário.

Código

A nossa implementação vai usar Python, uma linguagem muito utilizada em resolução de algoritmos, tanto em plataformas quanto leetcode quando em entrevistas de emprego.

deffive_sort(nums):i,j=0,len(nums)-1whilei<j:ifnums[j]==5:j-=1continueifnums[i]==5:nums[j],nums[i]=5,nums[j]j-=1i+=1returnnums
Enter fullscreen modeExit fullscreen mode

Passos do algoritmo:

  • Começamos os ponteiros nas pontas (começo e fim);
  • Respeitamos nosso caso base de iterar até que os ponteiros não tenham se encontrado;
  • Quando o 5 já está no fim do array, apenas decrementamos oj para que continuemos a avaliar os outros números;
  • Quando o 5 é encontrado no ponteiroi, precisamos fazer a troca com o número do ponteiroj;
  • Retornamos a lista modificada in-place.

Complexidade

Tempo: O(n)

Independente de quantos elementos tem o array, no pior caso precisamos iterar em todos elementos.

Espaço: O(1)

Nenhum espaço adicional é alocado. Como fazemos a modificação in-place, não há a criação de um array adicional.

Top comments(2)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
eduardoklosowski profile image
Eduardo Klosowski
Mestre em computação aplicada, programador backend com conhecimento de DevOps
  • Location
    Brasil
  • Joined

Estava olhando a função apresentada, e em toda repetição do laço é validado senums[j] não é5, o que lida com os5 que estão no final da lista, mas é um acesso à memória que o algoritmo precisa fazer. Pensando em remover esse primeiroif, é possível tratarnums[j] como incerto se é ou não5. Embora contra intuitivo, eu acredito que abrir mão da garantia que esseif da seja uma boa opção também. Como resultado, o algoritmo fica mais simples de ler por ter menos caminhos possíveis dentro do laço de repetição, é fácil identificar o que é feito em cada caso, e a cada execução a garantia de mover apenas um dos ponteiros uma única posição:

deffive_sort(nums):i,j=0,len(nums)-1whilei<j:ifnums[i]==5:nums[j],nums[i]=5,nums[j]j-=1else:i+=1returnnums
Enter fullscreen modeExit fullscreen mode

A desvantagem é que pode causar um pouco mais de trocas dos valores na memória. O que você acha?

CollapseExpand
 
mauricioabreu profile image
Maurício Antunes
I enjoy coding, video streaming and programming languages
  • Location
    Brazil
  • Work
    Software Developer @Globo
  • Joined

De fato ficou mais legível, mesmo, pelo motivo mencionado por você, de ter menos caminhos pra percorrer/assimilar. Obrigado pela contribuição!
Sobre a parte de ter mais swaps, não acho que seja problema.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

I enjoy coding, video streaming and programming languages
  • Location
    Brazil
  • Work
    Software Developer @Globo
  • Joined

More fromMaurício Antunes

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp