diff --git a/bolhas/bolhas-tutorial.pdf b/bolhas/bolhas-tutorial.pdf new file mode 100644 index 0000000..ea9ae43 Binary files /dev/null and b/bolhas/bolhas-tutorial.pdf differ diff --git a/bolhas/bolhas-tutorial.tex b/bolhas/bolhas-tutorial.tex new file mode 100644 index 0000000..1a43877 --- /dev/null +++ b/bolhas/bolhas-tutorial.tex @@ -0,0 +1,47 @@ +\documentclass[10pt]{article} +\usepackage[utf8]{inputenc} +\usepackage{amsmath,amsthm,amssymb} +\usepackage{fullpage} +\usepackage{url} +\pagenumbering{gobble} +\usepackage{hyperref} + +\title{ Tutorial: Bolhas} +\author{UVA - 11495} +\date{} +\begin{document} +\maketitle +O problema consiste em determinar o vencedor de um jogo baseado em trocas de elementos adjacentes de uma permutação, o que se traduz em calcular a paridade do número de inversões da sequência inicial. + +\subsection*{Representação do estado} + +\begin{itemize} + \item Uma \textbf{inversão} ocorre quando um elemento maior aparece antes de um elemento menor na sequência. + \item Cada movimento válido no jogo (trocar um par de elementos adjacentes fora de ordem) reduz o número total de inversões em exatamente $1$. + \item Como o jogo termina quando a sequência está ordenada (zero inversões) e Marcelo faz o primeiro movimento, a vitória depende exclusivamente da paridade das inversões: se for ímpar, Marcelo fará o último movimento e vencerá; se for par, Carlos vencerá. +\end{itemize} + +\subsection*{Estratégia de solução usando Divisão e Conquista (Merge Sort)} + +Para contar o número de inversões de forma eficiente, evitamos a contagem trivial de comparar todos os pares (que custaria $O(N^2)$) e utilizamos uma adaptação do algoritmo \textit{Merge Sort}. + +\begin{enumerate} + \item Leia o tamanho da sequência ($N$) e armazene a permutação inicial em um vetor. + \item Crie uma função recursiva baseada no \textit{Merge Sort} que divide o vetor ao meio até que os subvetores tenham tamanho $1$ (onde o número de inversões é $0$). + \item Na etapa de conquista (\textit{merge}): + \begin{itemize} + \item Mantenha dois ponteiros, um para o subvetor da esquerda e outro para o subvetor da direita. + \item Compare os elementos apontados. Se o elemento da direita for menor que o da esquerda, ele precisará saltar todos os elementos restantes do subvetor da esquerda para ser ordenado. + \item Nesse caso, adicione ao contador de inversões a quantidade exata de elementos restantes no subvetor da esquerda. + \item Copie o menor elemento para a posição correta do vetor principal para mantê-lo ordenado. + \end{itemize} + \item Após a execução de toda a recursão, avalie o número total de inversões contabilizadas. + \item Se o número de inversões for ímpar, imprima "Marcelo". Caso contrário, imprima "Carlos". +\end{enumerate} + +\subsection*{Complexidade} + +\begin{itemize} + \item \textbf{Espacial:} $O(N)$, devido à criação de vetores temporários auxiliares durante as etapas de intercalação do \textit{Merge Sort}, além de $O(\log N)$ referente ao espaço utilizado pela pilha de chamadas recursivas. + \item \textbf{Temporal:} $O(N \log N)$. O algoritmo divide a sequência de tamanho $N$ pela metade $\log N$ vezes. Em cada um desses níveis de recursão, a etapa de intercalação percorre os subvetores de forma linear, custando globalmente $O(N)$ por nível. +\end{itemize}\end{document} diff --git a/bolhas/bolhas.pdf b/bolhas/bolhas.pdf index 29b2519..1d1b4e3 100644 Binary files a/bolhas/bolhas.pdf and b/bolhas/bolhas.pdf differ diff --git a/bolhas/statement/tutorial.tex b/bolhas/statement/tutorial.tex index e69de29..3fb43ad 100644 --- a/bolhas/statement/tutorial.tex +++ b/bolhas/statement/tutorial.tex @@ -0,0 +1,34 @@ +O problema consiste em determinar o vencedor de um jogo baseado em trocas de elementos adjacentes de uma permutação, o que se traduz em calcular a paridade do número de inversões da sequência inicial. + +\subsection*{Representação do estado} + +\begin{itemize} + \item Uma \textbf{inversão} ocorre quando um elemento maior aparece antes de um elemento menor na sequência. + \item Cada movimento válido no jogo (trocar um par de elementos adjacentes fora de ordem) reduz o número total de inversões em exatamente $1$. + \item Como o jogo termina quando a sequência está ordenada (zero inversões) e Marcelo faz o primeiro movimento, a vitória depende exclusivamente da paridade das inversões: se for ímpar, Marcelo fará o último movimento e vencerá; se for par, Carlos vencerá. +\end{itemize} + +\subsection*{Estratégia de solução usando Divisão e Conquista (Merge Sort)} + +Para contar o número de inversões de forma eficiente, evitamos a contagem trivial de comparar todos os pares (que custaria $O(N^2)$) e utilizamos uma adaptação do algoritmo \textit{Merge Sort}. + +\begin{enumerate} + \item Leia o tamanho da sequência ($N$) e armazene a permutação inicial em um vetor. + \item Crie uma função recursiva baseada no \textit{Merge Sort} que divide o vetor ao meio até que os subvetores tenham tamanho $1$ (onde o número de inversões é $0$). + \item Na etapa de conquista (\textit{merge}): + \begin{itemize} + \item Mantenha dois ponteiros, um para o subvetor da esquerda e outro para o subvetor da direita. + \item Compare os elementos apontados. Se o elemento da direita for menor que o da esquerda, ele precisará saltar todos os elementos restantes do subvetor da esquerda para ser ordenado. + \item Nesse caso, adicione ao contador de inversões a quantidade exata de elementos restantes no subvetor da esquerda. + \item Copie o menor elemento para a posição correta do vetor principal para mantê-lo ordenado. + \end{itemize} + \item Após a execução de toda a recursão, avalie o número total de inversões contabilizadas. + \item Se o número de inversões for ímpar, imprima "Marcelo". Caso contrário, imprima "Carlos". +\end{enumerate} + +\subsection*{Complexidade} + +\begin{itemize} + \item \textbf{Espacial:} $O(N)$, devido à criação de vetores temporários auxiliares durante as etapas de intercalação do \textit{Merge Sort}, além de $O(\log N)$ referente ao espaço utilizado pela pilha de chamadas recursivas. + \item \textbf{Temporal:} $O(N \log N)$. O algoritmo divide a sequência de tamanho $N$ pela metade $\log N$ vezes. Em cada um desses níveis de recursão, a etapa de intercalação percorre os subvetores de forma linear, custando globalmente $O(N)$ por nível. +\end{itemize} \ No newline at end of file diff --git a/caching-offline/caching-offline-tutorial.pdf b/caching-offline/caching-offline-tutorial.pdf new file mode 100644 index 0000000..e5fdb1f Binary files /dev/null and b/caching-offline/caching-offline-tutorial.pdf differ diff --git a/caching-offline/caching-offline-tutorial.tex b/caching-offline/caching-offline-tutorial.tex new file mode 100644 index 0000000..b4d74f5 --- /dev/null +++ b/caching-offline/caching-offline-tutorial.tex @@ -0,0 +1,49 @@ +\documentclass[10pt]{article} +\usepackage[utf8]{inputenc} +\usepackage{amsmath,amsthm,amssymb} +\usepackage{fullpage} +\usepackage{url} +\pagenumbering{gobble} +\usepackage{hyperref} + +\title{ Tutorial: Caching Offline} +\author{} +\date{} +\begin{document} +\maketitle +O problema consiste em simular um gerenciador de cache e determinar o número mínimo de falhas de página. Como a sequência completa de requisições é conhecida previamente, podemos utilizar uma estratégia gulosa para resolver o problema. + +\subsection*{Representação do estado} + +\begin{itemize} + \item A memória principal (cache) é representada por um conjunto (\textit{hash set}), que armazena os identificadores das páginas atualmente carregadas, permitindo consultas em tempo constante. + \item O histórico futuro de cada página é mapeado em vetores, registrando todos os índices (momentos no tempo) em que cada página será requisitada. + \item Um vetor de ponteiros auxiliares acompanha qual a próxima ocorrência futura correspondente para cada página. +\end{itemize} + +\subsection*{Estratégia de solução usando Algoritmo Guloso} + +A estratégia ótima dita que, quando a cache estiver cheia e ocorrer uma falha, a página a ser substituída deve ser aquela que demorará mais tempo para ser referenciada novamente no futuro. + +\begin{enumerate} + \item Leia a capacidade da cache ($k$) e o tamanho da sequência de requisições ($v$). + \item Faça um pré-processamento da sequência de páginas: + \begin{itemize} + \item Armazene a sequência original em um vetor. + \item Para cada página lida, adicione o índice atual à sua respectiva lista de referências futuras. + \end{itemize} + \item Inicialize a cache vazia, o controle de progresso das referências futuras e o contador de falhas (\textit{misses}). + \item Percorra a sequência de requisições passo a passo: + \begin{itemize} + \item Se a página atual \textbf{não} estiver na cache, ocorreu uma falha de página. Incremente o contador de \textit{misses}. + \item Se a cache já estiver cheia (tamanho igual a $k$) no momento da falha, é necessário eleger uma página residente para remoção: + \begin{itemize} + \item Inspecione todas as páginas atualmente na cache. + \item Se alguma página não possuir mais requisições futuras, ela é a candidata ideal e deve ser escolhida para remoção imediata. + \item Caso contrário, compare a próxima requisição de todas e encontre aquela que vai demorar mais tempo para aparecer de novo (índice mais distante no futuro), removendo-a. + \end{itemize} + \item Insira a nova página na cache. + \item Ao final de cada iteração, independentemente de ter ocorrido acerto ou falha, avance o ponteiro de ocorrências da página que acabou de ser processada. + \end{itemize} + \item Ao término da simulação, imprima o total de falhas contabilizadas. +\end{enumerate}\end{document} diff --git a/caching-offline/caching-offline.pdf b/caching-offline/caching-offline.pdf index 098131d..b6be7ae 100644 Binary files a/caching-offline/caching-offline.pdf and b/caching-offline/caching-offline.pdf differ diff --git a/caching-offline/statement/tutorial.tex b/caching-offline/statement/tutorial.tex index e69de29..0704e01 100644 --- a/caching-offline/statement/tutorial.tex +++ b/caching-offline/statement/tutorial.tex @@ -0,0 +1,36 @@ +O problema consiste em simular um gerenciador de cache e determinar o número mínimo de falhas de página. Como a sequência completa de requisições é conhecida previamente, podemos utilizar uma estratégia gulosa para resolver o problema. + +\subsection*{Representação do estado} + +\begin{itemize} + \item A memória principal (cache) é representada por um conjunto (\textit{hash set}), que armazena os identificadores das páginas atualmente carregadas, permitindo consultas em tempo constante. + \item O histórico futuro de cada página é mapeado em vetores, registrando todos os índices (momentos no tempo) em que cada página será requisitada. + \item Um vetor de ponteiros auxiliares acompanha qual a próxima ocorrência futura correspondente para cada página. +\end{itemize} + +\subsection*{Estratégia de solução usando Algoritmo Guloso} + +A estratégia ótima dita que, quando a cache estiver cheia e ocorrer uma falha, a página a ser substituída deve ser aquela que demorará mais tempo para ser referenciada novamente no futuro. + +\begin{enumerate} + \item Leia a capacidade da cache ($k$) e o tamanho da sequência de requisições ($v$). + \item Faça um pré-processamento da sequência de páginas: + \begin{itemize} + \item Armazene a sequência original em um vetor. + \item Para cada página lida, adicione o índice atual à sua respectiva lista de referências futuras. + \end{itemize} + \item Inicialize a cache vazia, o controle de progresso das referências futuras e o contador de falhas (\textit{misses}). + \item Percorra a sequência de requisições passo a passo: + \begin{itemize} + \item Se a página atual \textbf{não} estiver na cache, ocorreu uma falha de página. Incremente o contador de \textit{misses}. + \item Se a cache já estiver cheia (tamanho igual a $k$) no momento da falha, é necessário eleger uma página residente para remoção: + \begin{itemize} + \item Inspecione todas as páginas atualmente na cache. + \item Se alguma página não possuir mais requisições futuras, ela é a candidata ideal e deve ser escolhida para remoção imediata. + \item Caso contrário, compare a próxima requisição de todas e encontre aquela que vai demorar mais tempo para aparecer de novo (índice mais distante no futuro), removendo-a. + \end{itemize} + \item Insira a nova página na cache. + \item Ao final de cada iteração, independentemente de ter ocorrido acerto ou falha, avance o ponteiro de ocorrências da página que acabou de ser processada. + \end{itemize} + \item Ao término da simulação, imprima o total de falhas contabilizadas. +\end{enumerate} \ No newline at end of file diff --git a/conversor-fonetico-generico/conversor-fonetico-generico-tutorial.pdf b/conversor-fonetico-generico/conversor-fonetico-generico-tutorial.pdf new file mode 100644 index 0000000..da1e78a Binary files /dev/null and b/conversor-fonetico-generico/conversor-fonetico-generico-tutorial.pdf differ diff --git a/conversor-fonetico-generico/conversor-fonetico-generico-tutorial.tex b/conversor-fonetico-generico/conversor-fonetico-generico-tutorial.tex new file mode 100644 index 0000000..c75e473 --- /dev/null +++ b/conversor-fonetico-generico/conversor-fonetico-generico-tutorial.tex @@ -0,0 +1,46 @@ +\documentclass[10pt]{article} +\usepackage[utf8]{inputenc} +\usepackage{amsmath,amsthm,amssymb} +\usepackage{fullpage} +\usepackage{url} +\pagenumbering{gobble} +\usepackage{hyperref} + +\title{ Tutorial: Conversor Fonético Genérico} +\author{Leetcode 127} +\date{} +\begin{document} +\maketitle +O problema de transformação de palavras exige encontrar o menor caminho entre uma palavra inicial e uma palavra final, alterando apenas uma letra por vez, com a restrição de que todas as palavras intermediárias devem pertencer a um dicionário fornecido. + +\subsection*{Representação do estado} + +\begin{itemize} + \item Cada palavra do dicionário (incluindo a palavra inicial) representa um nó em um grafo não direcionado. + \item Uma aresta conecta duas palavras se elas diferem em exatamente uma letra, uma "mutação" válida. + \item A transformação mais eficiente equivale a encontrar o caminho mais curto entre o nó inicial e o nó final neste grafo. +\end{itemize} + +\subsection*{Estratégia de solução usando BFS (Busca em Largura)} + +Como precisamos encontrar o menor número de passos em um grafo com arestas de peso uniforme e não direcionadas, a Busca em Largura (BFS) é a abordagem algorítmica ideal. + +\begin{enumerate} + \item Leia o número de palavras no dicionário ($N$) e o comprimento das palavras ($M$), seguidos das palavras inicial e final. + \item Armazene todas as palavras do dicionário em um conjunto (\textit{hash set}) para buscas eficientes. Insira também a palavra inicial neste conjunto, pois ela é o nosso ponto de partida. + \item Construa o grafo através de uma lista de adjacências: + \begin{itemize} + \item Para cada palavra no conjunto, itere sobre cada um de seus $M$ caracteres. + \item Substitua o caractere atual temporariamente por todas as 26 letras minúsculas do alfabeto ('a' a 'z'). + \item Se a nova palavra gerada após essa substituição também existir no dicionário, adicione-a à lista de adjacências da palavra original. + \end{itemize} + \item Inicialize a simulação da BFS: crie uma fila e insira a palavra inicial. Utilize um conjunto auxiliar para registrar os nós já visitados (\texttt{seen}), evitando ciclos infinitos. Defina a distância (profundidade) inicial da sequência como $1$. + \item Processe a fila operando por camadas (nível por nível): + \begin{itemize} + \item Descubra quantos elementos existem na fila atual. Este é o número de palavras no nível de profundidade atual. + \item Para cada uma dessas palavras, retire-a da fila e verifique: se for a palavra final desejada, a missão foi concluída! Imprima a profundidade atual e encerre. + \item Caso contrário, acesse a lista de adjacência da palavra. Para cada vizinho (mutação válida) que ainda não foi visitado, insira-o na fila e marque-o como visitado. + \end{itemize} + \item Ao terminar de processar todas as palavras da camada atual, incremente a profundidade. + \item Se a fila se esvaziar completamente e a palavra final nunca for atingida, a transformação é impossível sob essas regras. Retorne $0$. +\end{enumerate}\end{document} diff --git a/conversor-fonetico-generico/conversor-fonetico-generico.pdf b/conversor-fonetico-generico/conversor-fonetico-generico.pdf index e1babd5..0b8d1c8 100644 Binary files a/conversor-fonetico-generico/conversor-fonetico-generico.pdf and b/conversor-fonetico-generico/conversor-fonetico-generico.pdf differ diff --git a/conversor-fonetico-generico/statement/tutorial.tex b/conversor-fonetico-generico/statement/tutorial.tex index e69de29..e1abe2e 100644 --- a/conversor-fonetico-generico/statement/tutorial.tex +++ b/conversor-fonetico-generico/statement/tutorial.tex @@ -0,0 +1,33 @@ +O problema de transformação de palavras exige encontrar o menor caminho entre uma palavra inicial e uma palavra final, alterando apenas uma letra por vez, com a restrição de que todas as palavras intermediárias devem pertencer a um dicionário fornecido. + +\subsection*{Representação do estado} + +\begin{itemize} + \item Cada palavra do dicionário (incluindo a palavra inicial) representa um nó em um grafo não direcionado. + \item Uma aresta conecta duas palavras se elas diferem em exatamente uma letra, uma "mutação" válida. + \item A transformação mais eficiente equivale a encontrar o caminho mais curto entre o nó inicial e o nó final neste grafo. +\end{itemize} + +\subsection*{Estratégia de solução usando BFS (Busca em Largura)} + +Como precisamos encontrar o menor número de passos em um grafo com arestas de peso uniforme e não direcionadas, a Busca em Largura (BFS) é a abordagem algorítmica ideal. + +\begin{enumerate} + \item Leia o número de palavras no dicionário ($N$) e o comprimento das palavras ($M$), seguidos das palavras inicial e final. + \item Armazene todas as palavras do dicionário em um conjunto (\textit{hash set}) para buscas eficientes. Insira também a palavra inicial neste conjunto, pois ela é o nosso ponto de partida. + \item Construa o grafo através de uma lista de adjacências: + \begin{itemize} + \item Para cada palavra no conjunto, itere sobre cada um de seus $M$ caracteres. + \item Substitua o caractere atual temporariamente por todas as 26 letras minúsculas do alfabeto ('a' a 'z'). + \item Se a nova palavra gerada após essa substituição também existir no dicionário, adicione-a à lista de adjacências da palavra original. + \end{itemize} + \item Inicialize a simulação da BFS: crie uma fila e insira a palavra inicial. Utilize um conjunto auxiliar para registrar os nós já visitados (\texttt{seen}), evitando ciclos infinitos. Defina a distância (profundidade) inicial da sequência como $1$. + \item Processe a fila operando por camadas (nível por nível): + \begin{itemize} + \item Descubra quantos elementos existem na fila atual. Este é o número de palavras no nível de profundidade atual. + \item Para cada uma dessas palavras, retire-a da fila e verifique: se for a palavra final desejada, a missão foi concluída! Imprima a profundidade atual e encerre. + \item Caso contrário, acesse a lista de adjacência da palavra. Para cada vizinho (mutação válida) que ainda não foi visitado, insira-o na fila e marque-o como visitado. + \end{itemize} + \item Ao terminar de processar todas as palavras da camada atual, incremente a profundidade. + \item Se a fila se esvaziar completamente e a palavra final nunca for atingida, a transformação é impossível sob essas regras. Retorne $0$. +\end{enumerate} \ No newline at end of file