Análisis de ideas de resolución de problemas de Leetcode (38) 318-327

  1. Producto de longitud máxima de palabra
    Dada una matriz de cadenas de palabras, encuentre el valor máximo de longitud (palabra [i]) * longitud (palabra [j]), y estas dos palabras no contienen letras comunes. Puede pensar que cada palabra contiene solo letras minúsculas. Si no existen esas dos palabras, se devuelve 0.

Para facilitar la comparación, puede tomar operaciones de bits para almacenar el campo de bits de cada palabra y compararlas entre sí mediante operaciones de bits.

class Solution {
    
    
public:
    int str2int(const string& s) {
    
    
        int res = 0;
        for (auto c : s)
            res |= 1 << (c - 'a');
        return res;
    }
    int maxProduct(vector<string>& words) {
    
    
        int N = words.size();
        vector<int> m(N, 0);
        for (int i = 0; i < N; ++i)
            m[i] = str2int(words[i]);
        int res = 0;
        for (int i = 0; i < N; ++i) {
    
    
            for (int j = 0; j < i; ++j) {
    
    
                if ((m[i] & m[j]) == 0 && words[i].size() * words[j].size() > res)
                    res = words[i].size() * words[j].size();
            }
        }
        return res;
    }
};

  1. Interruptor de bombilla
    Inicialmente, n bombillas están apagadas. En la ronda 1, enciendes todas las bombillas. En la segunda ronda, apagas cada dos bombillas. En la tercera ronda, el interruptor se cambia cada tres bombillas (encender si está apagado, apagar si está encendido). En la ronda i, el interruptor se cambia cada i bombillas. Para la enésima ronda, solo cambia la última bombilla. Descubra cuántas bombillas están encendidas después de n rondas.

Solo el número cuadrado perfecto puede satisfacer el número impar de operaciones, el problema evoluciona para encontrar el número de 1 ~ n números cuadrados perfectos, 1 * 1, 2 * 2, ..., \ sqrt {n} * \ sqrt {n}, hay \ sqrt {n} n

class Solution {
    
    
public:
    int bulbSwitch(int n) {
    
    
        return sqrt(n);        
    }
};
  1. Número máximo de puntadas

Problema de algoritmo codicioso muy clásico

class Solution {
    
    
public:
// 返回数组nums中,从idx,到nums.size()-len-1中最大数的索引。
int findMaxIndex(vector<int> &nums, int idx, int len){
    
    	
    int maxIdx = idx;
    for (int i=idx; i<nums.size()-len; i++){
    
    
        if (nums[i] > nums[maxIdx]) maxIdx = i;
    }
    return maxIdx;
}
typedef pair<int,int> P;
vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
    
    
    int n = nums1.size();
    int m = nums2.size();
    set<P> start;	// 存储所有可能的起点索引
    start.insert(pair<int,int>{
    
    0,0});	// 数组1初始起点为0,数组2初始起点为0。
    vector<int> ans;	//存储答案
    while(k){
    
    
        int maxNum = -1;// 第i位数初始值
        set<P> temp;	// 存储第i位数可以导致的所有可能的起点索引
        for(auto p:start){
    
    	// 考虑能够到达第i位的所有可能的起点索引
            int s1 = p.first;
            int s2 = p.second;
            int len1 = max(0, k-(m-s2+1));
            int maxIdx1 = findMaxIndex(nums1, s1, len1);	// 数组1此时能够取的最大数的索引
            int maxNum1 = maxIdx1 >= n ? -1 : nums1[maxIdx1];// 该索引对应的最大数
            if(maxNum1>=maxNum){
    
    
                if(maxNum1>maxNum) temp.clear();	// 如果当前起点索引获得的最大数比之前起点索引获得的最大值还要大,那么之前起点索引得到后续可能索引(temp)可以不用考虑。
                maxNum = maxNum1;
                temp.insert({
    
    maxIdx1+1, s2});	// 更新temp
            }
            int len2 = max(0, k-(n-s1+1));
            int maxIdx2 = findMaxIndex(nums2, s2, len2);
            int maxNum2 = maxIdx2 >= m ? -1 : nums2[maxIdx2];
            if(maxNum2>=maxNum){
    
    
                if(maxNum2>maxNum) temp.clear();
                maxNum = maxNum2;
                temp.insert({
    
    s1, maxIdx2+1});
            }
        }
        ans.push_back(maxNum);	//	确定第i位数
        start.swap(temp);	    //	下一位所有可能的起点索引
        k--;
    }
    return ans;
}
};
  1. Cambiar Intercambio
    Dadas monedas de diferentes denominaciones y un monto total. Escribe una función para calcular la cantidad mínima de monedas necesarias para completar la cantidad total. Si ninguna combinación de monedas puede completar la cantidad total, devuelva -1.

Un problema típico de algoritmo codicioso, cada vez que se selecciona la denominación máxima y luego no hay devolución

class Solution {
    
    
public:
    void coinChange(vector<int>& coins, int amount, int c_index, int count, int& ans)
    {
    
    
        if (amount == 0)
        {
    
    
            ans = min(ans, count);
            return;
        }
        if (c_index == coins.size()) return;

        for (int k = amount / coins[c_index]; k >= 0 && k + count < ans; k--)
        {
    
    
            coinChange(coins, amount - k * coins[c_index], c_index + 1, count + k, ans);
        }
    }

    int coinChange(vector<int>& coins, int amount)
    {
    
    
        if (amount == 0) return 0;
        sort(coins.rbegin(), coins.rend());
        int ans = INT_MAX;
        coinChange(coins, amount, 0, 0, ans);
        return ans == INT_MAX ? -1 : ans;
    }
};
  1. Swing Sort 2
    Dada una matriz desordenada nums, reorganízala en el orden de nums [0] <nums [1]> nums [2] <nums [3] ...

Utilice el método de la mediana para dividir en dos matrices y luego alternar el empalme. Para lograr la complejidad del espacio O (1), las direcciones virtuales se asignan directamente a la matriz original en lugar de crear una nueva matriz.

class Solution {
    
    
public:
    void wiggleSort(vector<int>& nums) {
    
    
        int n = nums.size();

        // Find a median.
        auto midptr = nums.begin() + n / 2;
        nth_element(nums.begin(), midptr, nums.end());
        int mid = *midptr;

        // Index-rewiring.
        #define A(i) nums[(1+2*(i)) % (n|1)]

        // 3-way-partition-to-wiggly in O(n) time with O(1) space.
        int i = 0, j = 0, k = n - 1;
        while (j <= k) {
    
    
            if (A(j) > mid)
                swap(A(i++), A(j++));
            else if (A(j) < mid)
                swap(A(j), A(k--));
            else
                j++;
        }
    }
};


  1. Potencia de 3
    Dado un número entero, escribe una función para determinar si es una potencia de 3.

Preguntas matemáticas, fórmulas

class Solution {
    
    
public:
    bool isPowerOfThree(int n) {
    
    
    if(n <= 0) return false;
    double a = log10(n) / log10(3) ;        //换底
    return  a == floor(a);         //判断换底后的log3n是否为整数,即n是否为3的倍数
    }
};


  1. El número de secciones y
    dado los números una matriz de números enteros, y devuelve el número de intervalos entre [inferior, superior], que comprende inferior y superior.
    La suma de intervalo S (i, j) significa la suma de los elementos de i a j en nums, incluidos i y j (i ≤ j).

El método de la suma de intervalo ha aparecido varias veces antes, que consiste en guardar la suma de cada posición en 0 y simplemente restar.

typedef long long LL;
class Solution {
    
    
public:
    
    vector<LL> data;
    vector<int> tr;
    
    // 查找小于等于x的第一个数的下标,找不到返回0
    int binary_search1(LL x) {
    
    
        
        int l = 0, r = data.size() - 1;
        while (l < r) {
    
    
            int mid = l + r + 1 >> 1;
            if (data[mid] <= x) l = mid;
            else r = mid - 1;
        }
        if (l == 0 && data[0] > x) return 0;
        else return l + 1;
    }
    
    // 查找小于x的第一个数的下标,找不到返回0
    int binary_search2(LL x) {
    
    
        int l = 0, r = data.size() - 1;
        while (l < r) {
    
    
            int mid = l + r + 1 >> 1;
            if (data[mid] < x) l = mid;
            else r = mid - 1;
        }
        if (l == 0 && data[0] >= x) return 0;
        else return l + 1;
    }
    
    int lowbit(int x) {
    
    
        return x & -x;
    }
    
    int find(int x) {
    
    
        int ans = 0;
        for (int i = x; i; i -= lowbit(i)) ans += tr[i];
        return ans;
    }
    
    void add(int x, int c) {
    
    
        int n = tr.size() - 1;
        for (int i = x; i <= n; i += lowbit(i)) tr[i] += c;
    }
    
    int countRangeSum(vector<int>& nums, int lower, int upper) {
    
    
        int n = nums.size();
        LL sum = 0;
        vector<LL> s(n);
        for (int i = 0; i < n; i ++) {
    
    
            sum += nums[i];
            s[i] = sum;
        }
        data = s;
        data.push_back(0);
        sort(data.begin(), data.end());
        data.erase(unique(data.begin(), data.end()), data.end());
        tr = vector<int>(data.size() + 1);
        
//         for (int i = 0; i < data.size(); i ++) cout << data[i] << " ";
//         cout << endl;
        int ans = 0;
        int idx_zero = binary_search1(0);
        add(idx_zero, 1);
        for (auto x : s) {
    
    
            LL a = x - upper, b = x - lower;
            int idxa = binary_search2(a), idxb = binary_search1(b);
            int idxx = binary_search1(x);
            // cout << idxa << " " << idxb << " " << idxx << endl;
            if (idxb != 0) {
    
    
                if (idxa == 0) ans += find(idxb);
                else ans += find(idxb) - find(idxa);
            }
            add(idxx, 1);   
            // cout << ans << endl;
        }
        return ans;
    }
};




Supongo que te gusta

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