Preguntas de dificultad moderada que requieren paciencia: banco de preguntas de la entrevista de Huawei

Escribir en frente

Esta es la cuarta vez que termina las preguntas en el banco de preguntas de la entrevista de Huawei.

1245. El diámetro del árbol.

Déle este "árbol no dirigido", mida y devuelva su "diámetro": el número de lados del camino simple más largo en este árbol.

Utilizamos una matriz de bordes para representar un árbol no dirigido, donde los bordes [i] = [u, v] representan los bordes bidireccionales entre los nodos u y v.

Los nodos en el árbol se han marcado con los números en {0, 1, ..., edge.length}, y la marca en cada nodo es única.

Consejos:

  1. 0 <= bordes.longitud <10 ^ 4
  2. bordes [i] [0]! = bordes [i] [1]
  3. 0 <= bordes [i] [j] <= bordes.longitud
  4. los bordes formarán un árbol no dirigido

Solución: Obviamente el problema de dfs, pero lo más crítico es cómo dfs.

Fuerza bruta dfs (tiempo de espera)

Escribí un recorrido muy tonto de dfs, y realicé un dfs en todos los puntos con un solo lado conectado. De hecho, es obvio que hay muchas búsquedas redundantes.

Código:

class Solution {
private:
    int res = 0;
    int l = 0;
public:
    void dfs(vector<vector<int>>& b, int k, int d){
        bool f = false;
        for(int i=0; i<l; i++){
            if(b[k][i]==1){
                f = true;
                b[k][i] = 0;
                b[i][k] = 0;
                
                dfs(b,i,d+1);
                b[k][i] = 1;
                b[i][k] = 1;
            }
        }
        res = max(res,d);
    }
    int treeDiameter(vector<vector<int>>& edges) {
        if(edges.empty()) return 0;
        l = edges.size();
        vector<int> a(l+2,0);
        vector<vector<int>> b(l+1,vector<int>(l+1,0));
        for(int i=0; i<l; i++){
            a[edges[i][0]]++;
            a[edges[i][1]]++;
            b[edges[i][0]][edges[i][1]] = 1;
            b[edges[i][1]][edges[i][0]] = 1;
        }
        /*for(int i=0; i<=l; i++)
            cout<<a[i]<<' ';
        cout<<endl;*/
        for(int i=0; i<=l; i++){
            if(a[i]==1){
                dfs(b,i,0);
            }
        }
        return res;
    }
};

Dfs optimizado

  1. Seleccione aleatoriamente un punto como nodo raíz, aquí elegimos 0.
  2. Inicie dfs una vez desde la raíz y registre el nodo más alejado p1.
  3. Realice un dfs desde el nodo p1, y la profundidad registrada es la respuesta.

Código:

class Solution {
private:
    vector<vector<int>> graph;
    vector<bool> visited;
public:
    int treeDiameter(vector<vector<int>>& edges) {
        // build graph
        int l = edges.size();
        graph.resize(l+2);
        visited.resize(l+2);
        for(auto e: edges) {
            graph[e[0]].push_back(e[1]);
            graph[e[1]].push_back(e[0]);
        }
        pair<int, int> p1, p2;
        p1 = { -1, 0 };
        dfs(0, 0, p1);
        visited.assign(l+2, false);
        p2 = { -1, 0 };
        dfs(p1.first, 0, p2);
        return p2.second;
    }
    void dfs(int u, int depth, pair<int, int>& p) {
        visited[u] = true;
        if(depth > p.second) {
            p.second = depth;
            p.first = u;
        }
        for(int v: graph[u])
            if(!visited[v])
                dfs(v, depth + 1, p);
            
    }
};

1151. Combinando todos los intercambios mínimos 1

Dados los datos de una matriz binaria, debe combinar los 1 en cualquier posición de la matriz intercambiando posiciones y devolver el número mínimo de intercambios necesarios entre todos los posibles.

Consejos:

  1. 1 <= longitud de datos <= 10 ^ 5
  2. 0 <= datos [i] <= 1

Solución: La ventana deslizante es muy adecuada para este problema. El número de 1 se calcula como k, luego el tamaño de la ventana es p, el número de 1 en la ventana se actualiza durante el proceso de deslizamiento, y se registra el número máximo q, y pq es la respuesta.

Código:

class Solution {
public:
    int minSwaps(vector<int>& data) {
        if(data.empty()) return 0;
        int sum = 0;
        for(int i=0; i<data.size(); i++)
            sum += data[i];
        int res(0),c(0);
        for(int i=0; i<=sum-1; i++)
            c += data[i];
        res = max(res,c);
        for(int i=sum; i<data.size(); i++){
            c += data[i];
            c -= data[i-sum];
            res = max(res,c);
        }
        return (sum-res);
    }
};

239. Ventana deslizante máxima

Dado un conjunto de números, hay una ventana deslizante de tamaño k que se mueve desde el extremo izquierdo del conjunto hasta el extremo derecho del conjunto. Solo puede ver los k números en la ventana deslizante. La ventana deslizante se mueve solo una posición a la derecha a la vez.

Devuelve el valor máximo en la ventana deslizante.

Ejemplo:

Entrada: nums = [1,3, -1, -3,5,3,6,7] yk = 3

Salida: [3,3,5,5,6,7]

La última pregunta es una muy buena pregunta de ventana deslizante. Trabajemos en la plancha caliente y practiquemos otra pregunta de ventana deslizante (de hecho, porque una chica del grupo de preguntas del cepillo hizo esta pregunta de niebla).

Solución: Al principio, un grupo de personas entusiastas en el grupo dijo que esta era una fila prioritaria. Pensé que era razonable. Luego lo hice durante mucho tiempo y descubrí que había un problema. La ventana se movió y necesitaba ser eliminada. Este problema todavía se practica con múltiples soluciones.

Violencia

Código:

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        if(nums.empty() || k==0) return {};
        vector<int> res;
        for(int i=0; i+k<=nums.size(); i++){
            int m = nums[i];
            for(int j=i+1; j<=i+k-1; j++)
                m = max(m,nums[j]);
            res.push_back(m);
        }
        return res;
    }
};

Cola de doble final

Esta es la solución positiva a este problema. El uso de una cola de doble extremo puede mantener el encabezado y la cola de la cola al mismo tiempo. El índice se almacena en la cola. El encabezado de la cola siempre es el más grande. El encabezado de la cola aparece cuando se excede el tamaño de la ventana. Suelta el número más pequeño que el nuevo elemento.

Código:

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        if(nums.empty() || k==0) return {};
        deque<int> q;
        vector<int> res;
        for(int i=0; i<k; i++){//初始化队列
            while(!q.empty() && nums[i]>nums[q.back()])
                q.pop_back();
            q.push_back(i);
        }
        res.push_back(nums[q.front()]);
        for(int i=k; i<nums.size(); i++){
            if(!q.empty() && q.front()<=i-k)//超出窗口大小
                q.pop_front();
            while(!q.empty() && nums[i]>nums[q.back()])//删除队尾小的索引
                q.pop_back();
            q.push_back(i);
            res.push_back(nums[q.front()]);
        }
        return res;
    }
};

Programación dinámica

La idea de la planificación dinámica de esta pregunta es muy inteligente: aquí publicaré una explicación oficial, que es muy clara, y no entraré en detalles. https://leetcode-cn.com/problems/sliding-window-maximum/solution/hua-dong-chuang-kou-zui-da-zhi-by-leetcode-3/

Código:

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        if(nums.empty() || k==0) return {};
        vector<int> res,left;
        vector<int> right(nums.size(),0);
        int t = 0;
        for(int i=0; i<nums.size(); i++){
            if(i%k==0){
                t = nums[i];
            }
            t = max(t,nums[i]);
            left.push_back(t);
        }

        t = nums[nums.size()-1];
        for(int i=nums.size()-1; i>=0; i--){
            if((i+1) % k==0){
                t = nums[i];
            }
            t = max(t,nums[i]);
            right[i] = t;
        }

        for(int i=0; i+k<=nums.size(); i++)
            res.push_back(max(left[i+k-1],right[i]));
        return res;
    }
};

254. Combinación de factores.

Los enteros se pueden ver como el producto de sus factores.

Por ejemplo:

  8 = 2 x 2 x 2;

  = 2 x 4.

Implemente una función que reciba un entero n y devuelva todas las combinaciones de factores del entero.

Nota:

  1. Puede suponer que n siempre es positivo.
  2. El factor debe ser mayor que 1 y menor que n.

Ejemplo:

Entrada: 32

Salida:

[

 [2, 16],

 [2, 2, 8],

 [2, 2, 2, 4],

 [2, 2, 2, 2, 2],

 [2, 4, 4 ],

 [4, 8]

]

Solución: Obviamente dfs, pero la dificultad es el almacenamiento, de acuerdo con el orden de almacenamiento dado en el ejemplo, puede encontrar la idea de dfs, cada vez que desmonte el último bit, y luego asegúrese de que la secuencia no se caiga.

Código:

class Solution {
private:
    vector<vector<int>> res;//存储答案
public:
    void dfs(vector<int>& m){
        res.push_back(m);
        for(int i=m[m.size()-2]; i<=sqrt(m[m.size()-1]); i++){//拆解最后一位数字,范围:[倒数第二位数,最后一位数的平方根]
            if(m[m.size()-1]%i==0){
                vector<int> temp(m.begin(),m.end()-1);
                temp.push_back(i);
                temp.push_back(m[m.size()-1]/i);
                dfs(temp);
            }
        }
    }
    vector<vector<int>> getFactors(int n) {
        for(int i=2; i<=sqrt(n); i++){
            if(n%i==0){
                vector<int> temp = {i , n/i};
                dfs(temp);
            }
        }
        return res;
    }
};

Resumen de esta pregunta: esta pregunta no es difícil desde la perspectiva de las ideas y los algoritmos, pero lo más temido acerca de la recursión es en realidad el almacenamiento. La solución del gran problema en la solución del problema al que me refiero aquí es más conveniente para operar con un vector unidimensional temporal. .

554. pared de ladrillo

Delante de usted hay una pared cuadrada de ladrillos compuesta por múltiples filas de ladrillos. Estos ladrillos tienen la misma altura pero diferentes anchos. Ahora debe dibujar una línea vertical de arriba a abajo que pase por la menor cantidad de ladrillos.

El muro de ladrillos está representado por una lista de filas. Cada fila es una lista de enteros que representan el ancho de cada ladrillo de izquierda a derecha.

Si la línea que dibuja solo pasa por el borde del ladrillo, no cuenta a través del ladrillo. Debe descubrir cómo dibujar para minimizar la cantidad de ladrillos que cruza esta línea y devolver la cantidad de ladrillos que se cruzan.

No puede dibujar una línea a lo largo de uno de los dos bordes verticales de la pared, por lo que obviamente no pasa a través de un ladrillo.

Ejemplo:

Ingrese:
[1,2,2,1],

[3,1,2],

[1,3,2],

[2,4],

[3,1,2],

[1,3,1 , 1]]

Salida: 2

Solución:

Tabla hash

La idea no es demasiado difícil. Los ladrillos en cada fila se agregan con todos los anchos anteriores, y luego debido a que estos anchos aumentan linealmente, después de agregarlos, use hashmap para registrar el número del mismo ancho. El más grande es la posición de la respuesta.

Código:

class Solution {
public:
    int leastBricks(vector<vector<int>>& wall) {
        int l = wall.size();
        for(int i=0; i<wall.size(); i++){
            for(int j=1; j<wall[i].size(); j++){
                wall[i][j] += wall[i][j-1];
            }
        }
        int m = wall[0][wall[0].size()-1];
        unordered_map<int,int> a;
        for(int i=0; i<wall.size(); i++)
            for(int j=0; j<wall[i].size()-1; j++){
                auto pos = a.find(wall[i][j]);
                if(pos!=a.end()){
                    a[wall[i][j]]++;
                }
                else{
                    a[wall[i][j]] = 1;
                }
            }
        int res = 0;
        for(auto it = a.begin(); it!=a.end(); it++){
            res = max(res,it->second);
        }
        return l-res;
    }
};

Ordenar

Resuma primero, luego use una matriz unidimensional para almacenar todos los anchos, y luego ordene, un poco más rápido que el método anterior.

Código:

class Solution {
public:
    int leastBricks(vector<vector<int>>& wall) {
        int l = wall.size();
        for(int i=0; i<wall.size(); i++){
            for(int j=1; j<wall[i].size()-1; j++){
                wall[i][j] += wall[i][j-1];
            }
        }
        vector<int> a;
        for(int i=0; i<wall.size(); i++)
            for(int j=0; j<wall[i].size()-1; j++)
                a.push_back(wall[i][j]);
        sort(a.begin(),a.end());
        int res = 0;
        int c=1;
        for(int i=1; i<a.size(); i++)
            if(a[i]!=a[i-1]){
                res = max(res,c);
                c = 1;
            }
            else
                ++c;
        if(!a.empty())res = max(res,c);
        return l-res;
    }
};

562. El segmento continuo más largo de 1 línea en la matriz

Dada una matriz 01 M, encuentre el segmento continuo más largo de 1 línea en la matriz. Este segmento de línea puede ser horizontal, vertical, diagonal o diagonal.

Ejemplo:

Entrada:

[[0,1,1,0], [0,1,1,0],

 [0,0,0,1]

 ]

Salida: 3

Consejo: El número de elementos en una matriz dada no excederá 10,000.

Solución: El problema dp solo debe hacerse en cuatro direcciones, el código es muy largo y debe prestar atención al problema del límite.

Código:

class Solution {
public:
    int longestLine(vector<vector<int>>& a) {
        if(a.empty() || a[0].empty()) return 0;
        int m = a.size();
        int n = a[0].size();
        int res = 0;
        for(int i=0; i<m; i++)
            for(int j=0; j<n; j++)
                res += a[i][j];
        if(res==0 || res==1) return res;
        vector<vector<int>> dp(m+1,vector<int>(n+1,0));
        res = 0;
        //横向
        dp[0][0] = a[0][0];
        for(int i=1; i<m; i++)
            dp[i][0] = a[i][0];//初始化第一列
        for(int i=0; i<m; i++)
            for(int j=1; j<n; j++)
                if(a[i][j])
                    dp[i][j] = dp[i][j-1] + 1;
        for(int i=0; i<m; i++)
            for(int j=0; j<n; j++)
                res = max(res,dp[i][j]);
        for(int i=0; i<m; i++)
            for(int j=0; j<n; j++)
                dp[i][j] = 0;//清零
        cout<<1<<endl;
        //竖向
        dp[0][0] = a[0][0];
        for(int i=0; i<n; i++)
            dp[0][i] = a[0][i];//初始化第一行
        for(int i=1; i<m; i++)
            for(int j=0; j<n; j++)
                if(a[i][j])
                    dp[i][j] = dp[i-1][j] + 1;
        for(int i=0; i<m; i++)
            for(int j=0; j<n; j++)
                res = max(res,dp[i][j]);
        for(int i=0; i<m; i++)
            for(int j=0; j<n; j++)
                dp[i][j] = 0;//清零
        //斜向
        dp[0][0] = a[0][0];
        for(int i=0; i<n; i++)
            dp[0][i] = a[0][i];//初始化第一行
        for(int i=0; i<m; i++)
            dp[i][0] = a[i][0];//初始化第一列
        for(int i=1; i<m; i++)
            for(int j=1; j<n; j++)
                if(a[i][j])
                    dp[i][j] = dp[i-1][j-1] + 1;
        for(int i=0; i<m; i++)
            for(int j=0; j<n; j++)
                res = max(res,dp[i][j]);
        for(int i=0; i<m; i++)
            for(int j=0; j<n; j++)
                dp[i][j] = 0;//清零
        //反斜向
        dp[0][0] = a[0][0];
        for(int i=0; i<n; i++)
            dp[0][i] = a[0][i];//初始化第一行
        for(int i=0; i<m; i++)
            dp[i][n-1] = a[i][n-1];//初始化最后一列
        for(int i=1; i<m; i++)
            for(int j=0; j<n-1; j++)
                if(a[i][j])
                    dp[i][j] = dp[i-1][j+1] + 1;
        for(int i=0; i<m; i++)
            for(int j=0; j<n; j++)
                res = max(res,dp[i][j]);
        for(int i=0; i<m; i++)
            for(int j=0; j<n; j++)
                dp[i][j] = 0;//清零
        return res;
    }
};
Publicado 13 artículos originales · ganó 27 · vistas 2649

Supongo que te gusta

Origin blog.csdn.net/u011708337/article/details/105007458
Recomendado
Clasificación