Ordenação Léxica, Caractere Único e Caminho Máximo em Estrutura de Diretórios

1. Números em Ordem Léxica

Dado um inteiro n, o objetivo é retornar os números de 1 a n organizados em ordem lexicográfica — ou seja, como se estivessem ordenados como strings. Por exemplo, para n = 13, a sequência correta é [1, 10, 11, 12, 13, 2, 3, ..., 9]. A abordagem direta com comparação de strings seria ineficiente para entradas grandes (até 5.000.000), exigindo uma solução mais inteligente.

A estratégia anvolve percorrer os números como em uma árvore digital (trie), onde cada nível adiciona um dígito ao número atual. Isso pode ser implementado com uma busca em profundidade iterativa. Em vez de gerar todos os números e ordená-los, construímos a sequência diretamente navegando nos "filhos" de cada número (multiplicar por 10 e adicionar dígitos de 0 a 9), respeitando o limite n.

class Solution {
public:
    vector<int> generateLexOrder(int limit) {
        vector<int> result;
        int current = 1;

        for (int i = 0; i < limit; ++i) {
            result.push_back(current);
            
            if (current * 10 <= limit) {
                current *= 10;  // Vai para o próximo nível (ex: 1 -> 10)
            } else {
                while (current % 10 == 9 || current + 1 > limit) {
                    current /= 10;  // Volta ao pai
                }
                current++;  // Avança para o próximo irmão
            }
        }
        return result;
    }
};

2. Primeiro Caractere Não Repetido em uma String

O problema pede o índice do primeiro caractere em uma string que aparece exatamente uma vez. A entrada contém apenas letras minúsculas, o que permite usar um vetor fixo de tamanho 26 como tabela de frequência.

A solução passa pela string duas vezes: na primeira, conta as ocorrências de cada letra; na segunda, verifica qual é a primeira com contagem igual a 1. Para otimizar espaço e clareza, podemos armazenar diretamente o índice da primeira aparição e marcar repetições com um valor negativo.

class Solution {
public:
    int findFirstUniqueChar(const string& s) {
        vector<int> firstIndex(26, -2);  // -2: não visto; -1: repetido; >=0: índice da primeira ocorrência

        for (int i = 0; i < s.size(); ++i) {
            int idx = s[i] - 'a';
            if (firstIndex[idx] == -2) {
                firstIndex[idx] = i;
            } else {
                firstIndex[idx] = -1;  // Marca como duplicado
            }
        }

        int minPos = INT_MAX;
        for (int pos : firstIndex) {
            if (pos >= 0 && pos < minPos) {
                minPos = pos;
            }
        }

        return minPos == INT_MAX ? -1 : minPos;
    }
};

3. Comprimento do Maior Caminho Absoluto de Arquivo

Dada uma string que representa uma estrutura hierárquica de arquivos com separadores '\n' e '\t', o desafio é calcular o comprimento máximo de um caminho completo até um arquivo (identificado pela presença de '.'). Cada nível de subdiretório é indicado por tabulações consecutivas.

A ideia é simular uma travessia em profundidade usando um vetor acumulador que guarda o comprimento dos segmentos em cada nível de profundidade. Ao encontrar um arquivo, somamos os tamanhos dos diretórios anteriores mais as barras '/' necessárias, e comparamos com o máximo encontrado.

class Solution {
public:
    int findMaxFilePathLength(const string& input) {
        if (input.empty()) return 0;

        vector<int> levelLength(300, 0);  // Armazena o comprimento do nome no nível i
        int maxLength = 0;
        int i = 0;

        while (i < input.size()) {
            int depth = 0;
            while (i < input.size() && input[i] == '\t') {
                ++depth;
                ++i;
            }

            int start = i;
            bool isFile = false;
            while (i < input.size() && input[i] != '\n') {
                if (input[i] == '.') isFile = true;
                ++i;
            }

            int nameLength = i - start;
            levelLength[depth] = nameLength;

            if (isFile) {
                int totalLength = 0;
                for (int d = 0; d <= depth; ++d) {
                    totalLength += levelLength[d];
                    if (d < depth) totalLength++;  // Adiciona '/'
                }
                if (totalLength > maxLength) {
                    maxLength = totalLength;
                }
            }

            if (i < input.size()) ++i;  // Pula '\n'
        }

        return maxLength;
    }
};

Tags: LeetCode dfs Trie Hash Table String Parsing

Publicado em 9-13 15:32