Secuencia Count and Say: Generación e Implementaciones en C++

La secuencia count-and-say es una serie de números enteros que inicia así: 1, 11, 21, 1211, 111221, ...

Se interpreta como: 1 se lee como "un 1" → 11; 11 se lee como "dos 1s" → 21; 21 se lee como "un 2, luego un 1" → 1211.

Dado un entero n, el objetivo es generar la n-ésima secuencia, representada como una cadena de caracteres.

A continuación, se presentan varias implementaciones en C++ para resolver este problema.

class Solucion {
public:
    string generarSiguiente(const string &entrada) {
        stringstream flujo;
        int repeticiones = 0;
        char caracterActual = entrada[0];
        for (size_t pos = 0; pos <= entrada.size(); ++pos) {
            if (caracterActual == entrada[pos]) {
                ++repeticiones;
            } else {
                flujo << repeticiones << caracterActual;
                repeticiones = 1;
                caracterActual = entrada[pos];
            }
        }
        return flujo.str();
    }

    string countAndSay(int n) {
        if (n <= 0) return "";
        string resultado = "1";
        for (int paso = 1; paso < n; ++paso) {
            resultado = generarSiguiente(resultado);
        }
        return resultado;
    }
};

Otra aproximación utiliza un bucle while para procesar la cadena:

class Solucion {
public:
    string siguienteLectura(const string &s) {
        stringstream flujo;
        int conteo, idx = 0, longitud = s.length();
        while (idx < longitud) {
            conteo = 0;
            while (idx + 1 < longitud && s[idx] == s[idx + 1]) {
                idx++;
                conteo++;
            }
            flujo << conteo + 1 << s[idx];
            idx++;
        }
        return flujo.str();
    }

    string countAndSay(int n) {
        string res = "";
        if (n == 0) return res;
        res = "1";
        if (n == 1) return "1";
        while (n > 1) {
            res = siguienteLectura(res);
            n--;
        }
        return res;
    }
};

Una implementación alternativa emplea bucles anidados para contar caracteres consecutivos:

class Solucion {
public:
    string countAndSay(int n) {
        if (n == 0) return NULL;
        if (n == 1) return "1";
        int contador = 1;
        string cadenaActual = "1";
        string cadenaSiguiente;
        int iterador = 1;
        if (n >= 2) {
            cadenaActual = "11";
            iterador = 2;
        }
        int i = 0;
        while (iterador < n && n > 1) {
            cadenaSiguiente = "";
            for (i = 0; i < cadenaActual.size(); i++) {
                for (int m = i; m < cadenaActual.size() - 1; m++) {
                    if (cadenaActual[m] == cadenaActual[m + 1]) {
                        contador++;
                        i++;
                    }
                    if (cadenaActual[m] != cadenaActual[m + 1]) {
                        break;
                    }
                }
                cadenaSiguiente += to_string(contador) + cadenaActual[i];
                contador = 1;
            }
            cadenaActual = cadenaSiguiente;
            iterador++;
        }
        return cadenaActual;
    }
};

Finalmente, una solución compacta utiliza un enfoque iterativo con punteros:

class Solucion {
public:
    string countAndSay(int n) {
        if (n == 0) return " ";
        if (n == 1) return "1";
        string base = "1";
        string temporal;
        for (int i = 1; i < n; ++i) {
            temporal.clear();
            int repeticiones = 1;
            for (int j = 0; j < base.size(); ++j) {
                while (j + 1 < base.size()) {
                    if (base[j] == base[j + 1]) {
                        ++repeticiones;
                        ++j;
                    } else {
                        break;
                    }
                }
                temporal.push_back(repeticiones + '0');
                temporal.push_back(base[j]);
                repeticiones = 1;
            }
            base = temporal;
        }
        return base;
    }
};

Etiquetas: C++ leetcode secuencia_count_and_say algoritmos manipulación_de_cadenas

Publicado el 6-11 03:12