[Backtrack] [leetcode] Código Gray

tema:

La codificación gris es un sistema numérico binario en el que dos valores consecutivos difieren solo en un dígito.

Dado un número entero no negativo n que representa el número total de dígitos en el código, imprima su secuencia de código Gray. Incluso si hay varias respuestas diferentes, solo necesita devolver una de ellas.

La secuencia del código Gray debe comenzar con 0.

Ejemplo 1:

Entrada: 2
Salida: [0,1,3,2]
Explicación:
00 - 0
01 -. 1.
11 -. 3
10 - 2

Para un n dado, su secuencia de código Gray no es única.
Por ejemplo, [0,2,3,1] también es una secuencia de código Gray válida.

00-0
10 - 2
11 - 3
01 - 1

fuente:

89. Codificación gris

Idea de resolución de problemas 1: retroceder

Defina una ruta para almacenar los resultados intermedios y la salida inmediatamente una vez que se cumplan las condiciones.

  • El resultado cumple la condición: el número en la ruta ha alcanzado
  • Condición de llamada recursiva: si los códigos grises del número anterior no están en la ruta, son recursivos.

Si el número actual es 000, su siguiente código gris puede ser 001,010,100. Concéntrese en la función gris en el código, modifique el p-ésimo dígito y vuelva: primero determine si el p-ésimo dígito es 0 o 1. Si es 0, la operación OR se puede modificar a 1; si es 1, la operación AND se puede modificar a 0.

class Solution {
public:
    vector<int> result;
    vector<int> path;
    bool ok;
    vector<int> grayCode(int n) {
        vector<bool> flag(1<<n, false); // 记录数字是否已在结果列表中
        ok = false;
        path.push_back(0);
        flag[0] = true;
        back(n, flag);
        return result;
    }
    void back(int n, vector<bool>& flag) {
        if (path.size() == flag.size()) {
            result = path;
            ok = true;
            return;
        }
        int pre = path[path.size() - 1]; // 结果列表中最后一个数字
        for (int i = 0; i < n; i++) {
            if (ok) break;
            int k = gray(pre, i); // 最后一个数字的改变第i位后的数字
            if (!flag[k]) {
                flag[k] = true;
                path.push_back(k);
                back(n, flag);
                path.pop_back();
                flag[k] = false;
            }
        }
    }
    int gray(int v, int p) {
        int a = (0x1 << p);
        if ((a & v) == 0) {
            return v | a;
        } else {
            return v & (~a);
        }
    }
};

Idea para resolución de problemas 2: encontrar la ley

El envío de código retrospectivo encontró que la eficiencia operativa es muy baja: tiempo de ejecución: 20 ms, derrotando al 12,37% de los usuarios en todos los envíos de C ++.

Curioso, fui a leer la solución y descubrí que esta pregunta todavía tiene un patrón a seguir. No escribí el código. Enumeré el patrón que encontré a continuación:

Cuando n = 1, el resultado es [0,1],

Cuando n = 2, se divide en 3 pasos:

  1. Tome el resultado de n = 1 y obtenga [0,1].
  2. Toma [0,1] y haz una copia en el espejo para obtener [1,0]. Los dos se fusionan en [0,1 | 1, 0], con un símbolo | en el medio, y llámalo espejo por ahora.
  3. Agregue 0 al comienzo de cada número en el lado izquierdo del espejo y 1 en el lado derecho para obtener [00, 01 | 11, 10], este es el resultado

Cuando n = 3,4,5 ..., repita los 3 pasos anteriores en secuencia.

Cuando n = 3,

  1. Tome el resultado de n = 2 y obtenga [00, 01, 11, 10].
  2. Eche un vistazo a [00, 01, 11, 10] y haga una copia para obtener [10, 11, 01, 00]. Los dos se combinan para obtener [00, 01, 11, 10 | 10, 11, 01, 00].
  3. Agregue 0 al comienzo de cada número en el lado izquierdo del espejo y 1 en el lado derecho para obtener [000, 001, 011, 010 | 110, 111, 101, 100], este es el resultado

Supongo que te gusta

Origin blog.csdn.net/hbuxiaoshe/article/details/115123734
Recomendado
Clasificación