Análisis de ideas de resolución de problemas de Leetcode (30) 214-220

  1. La cadena de palíndromo más corta
    Dada una cadena s, puede convertirla en una cadena de palíndromo agregando caracteres delante de la cadena. Busque y devuelva el palíndromo más corto que se pueda convertir de esta manera.

En esta pregunta, puede usar un carro tirado por caballos para obtener la subcadena palíndromo más larga y luego agregarla al revés. KMP también se puede utilizar para resolver

class Solution {
    
    
public:
    string shortestPalindrome(string s)
    {
    
    
        int n = s.size();
        string rev(s);
        reverse(rev.begin(), rev.end());
        string s_new = s + "#" + rev;
        int n_new = s_new.size();
        vector<int> f(n_new, 0);
        for (int i = 1; i < n_new; i++) {
    
    
            int t = f[i - 1];
            while (t > 0 && s_new[i] != s_new[t])
                t = f[t - 1];
            if (s_new[i] == s_new[t])
                ++t;
            f[i] = t;
        }
        return rev.substr(0, n - f[n_new - 1]) + s;
    }
};
  1. K-ésimo elemento más grande
    en la matriz Encuentre el k-ésimo elemento más grande en la matriz sin clasificar. Tenga en cuenta que lo que necesita encontrar es el k-ésimo elemento más grande después de ordenar la matriz, no el k-ésimo elemento diferente.

Al ver los elementos K, sabe que el montón se puede resolver y también puede usar el algoritmo de selección para resolverlo. La idea de elegir un algoritmo es dividir y conquistar

#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;

class Solution
{
    
    
public:
    int findKthLargest(vector<int> &nums, int k)
    {
    
    
        int result = 0;
        int numsSize = int(nums.size());
        if (numsSize == 0 || k > numsSize)
        {
    
    
            return 0;
        }
        //寻找第kMIN小的数
        int kMin = numsSize - k + 1;
        result = select(nums, 0, numsSize - 1, kMin);
        return result;
    }

    int select(vector<int> &nums, int left, int right, int target)
    {
    
    
        if (left == right)
        {
    
    
            return nums[left];
        }
        int cut = partition(nums, left, right);
        //当前第currentResult小的元素
        int currentResult = cut - left + 1;
        if (target == currentResult)
        {
    
    
            return nums[cut];
        }
        else if (target < currentResult)
        {
    
    
            return select(nums, left, cut - 1, target);
        }
        else
        {
    
    
            //寻找接下来第target - currentResult小的数
            return select(nums, cut + 1, right, target - currentResult);
        }
        return 0;
    }

    int partition(vector<int> &nums, int left, int right)
    {
    
    
        int cut = nums[right];
        //i指向大堆的最左边的数,j指向下一个判断的数
        int i = left;
        for (int j = left; j < right; j++)
        {
    
    
            if (nums[j] <= cut)
            {
    
    
                exchange(nums[i], nums[j]);
                i++;
            }
        }
        exchange(nums[i], nums[right]);
        return i;
    }

    void exchange(int &a, int &b)
    {
    
    
        int tmpInt = a;
        a = b;
        b = tmpInt;
        return;
    }
};

  1. La suma de combinación 3
    encuentra todas las k combinaciones que suman n. Solo se permiten números enteros positivos del 1 al 9 en la combinación y no hay números repetidos en cada combinación.

Esta pregunta se puede resolver fácilmente utilizando el método de retroceso

class Solution {
    
    
public:
    vector<vector<int>> combinationSum3_dfs(int k, int n, int now, int status) {
    
    
        if(k == 0 && n == 0) {
    
      //一个有用的结果
            vector<int> res;
            for(int i = 1; i < 10; i++) {
    
    
                if((2 << i) & status) res.push_back(i);
            }
            return {
    
    res};
        }
        vector<vector<int>> res;
        while(now < 10 && n >= now) {
    
       //能够继续dfs的条件
            auto r = combinationSum3_dfs(k - 1, n - now, now + 1, status | (2 << now));
            res.insert(res.end(), r.begin(), r.end()); //结果合并
            now++;
        }
        return res;
    }
    vector<vector<int>> combinationSum3(int k, int n) {
    
    
        return combinationSum3_dfs(k, n, 1, 0);
    }
};

  1. Hay elementos duplicados
    Dada una matriz de números enteros, juzgue si hay elementos duplicados.
    Si algún valor aparece al menos dos veces en la matriz, la función devuelve verdadero. Si cada elemento de la matriz es diferente, se devuelve falso.

Pregunta muy simple, almacenamiento y búsqueda de tablas hash

class Solution {
    
    
public:
    bool containsDuplicate(vector<int>& nums) {
    
    
        std::unordered_map<int, int> map;
        for (auto i : nums)
        {
    
    
            map[i]++;
            if (map[i] > 1)
                return true;
        }
        return false;
    }
};
  1. Problema del horizonte

Hay muchas soluciones para este problema: la solución más intuitiva es tomar la línea de escaneo para escanear de izquierda a derecha, comparar las alturas guardadas en el eje X actual y generar el valor más alto. Del mismo modo, también podemos utilizar una lista doblemente enlazada para escanear. Además, también se puede adoptar la idea de divide y vencerás: si no hay edificio, el valor es 0, si hay un edificio, el valor se divide y se conquista.

class Solution {
    
    
public:
    vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
    
    
        multiset<pair<int, int>> all;
        vector<vector<int>> res;
        
        for (auto& e : buildings) {
    
    
            all.insert(make_pair(e[0], -e[2])); // critical point, left corner
            all.insert(make_pair(e[1], e[2])); // critical point, right corner
        }
        
        multiset<int> heights({
    
    0}); // 保存当前位置所有高度。
        vector<int> last = {
    
    0, 0}; // 保存上一个位置的横坐标以及高度
        for (auto& p : all) {
    
    
            if (p.second < 0) heights.insert(-p.second); // 左端点,高度入堆
            else heights.erase(heights.find(p.second)); // 右端点,移除高度
            
            // 当前关键点,最大高度
            auto maxHeight = *heights.rbegin();
            
            // 当前最大高度如果不同于上一个高度,说明这是一个转折点
            if (last[1] != maxHeight) {
    
    
                // 更新 last,并加入结果集
                last[0] = p.first;
                last[1] = maxHeight;
                res.push_back(last);
            }
        }
        
        return res;
    }
};

  1. Hay elementos duplicados 2
    Dada una matriz de enteros y un entero k, juzgue si hay dos índices iyj diferentes en la matriz, de modo que nums [i] = nums [j], y el valor absoluto de la diferencia entre i y j es como máximo k.

Tan simple como la primera pregunta, la tabla hash se resuelve directamente, pero aquí hay un detalle de optimización: no necesitamos almacenar todos los números, solo necesitamos usar una ventana deslizante de tamaño k.

class Solution {
    
    
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
    
    
        unordered_map<int, vector<int>> map;
        for (int i = 0; i < nums.size(); i++)
        {
    
    
            map[nums[i]].push_back(i);
            if (map[nums[i]].size() > 1)
            {
    
    
                for (int j = 1; j < map[nums[i]].size(); j++)
                {
    
    
                    if (map[nums[i]][j] - map[nums[i]][j - 1] <= k)
                        return true;
                }
            }
        }
        return false;
    }
};
  1. Hay elementos duplicados 3
    En la matriz de enteros nums, si hay dos subíndices i y j, de modo que el valor absoluto de la diferencia entre nums [i] y nums [j] sea menor o igual que t, y satisfaga el valor absoluto de la diferencia entre i y j Menor o igual que K.
    Devuelve verdadero si existe, falso si no existe.

Hay muchas formas de resolver este problema, el método más excelente es la idea de clasificación de cubos o la forma de ventana deslizante.

class Solution {
    
    
public:
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
    
    
        if (k < 1 || t < 0 || nums.empty()) return false;
        int N = nums.size();
        map<long, int> m{
    
    {
    
    nums[0], 1}};
        for (int i = 1; i < N; ++i) {
    
    
            auto it = m.lower_bound(nums[i]);
            if (it != m.end() && abs(it->first - (long)nums[i]) <= t) return true;
            if (it != m.begin() && abs((--it)->first - (long)nums[i]) <= t)  return true;
            ++m[nums[i]];
            if (i - k >= 0 && --m[nums[i - k]] == 0) m.erase(nums[i - k]);
        }
        return false;
    }
};



Supongo que te gusta

Origin blog.csdn.net/u013354486/article/details/106805064
Recomendado
Clasificación