Tabla hash [Suma de números X]

Guía de preguntas

para resumir(***)

1. Reducir la complejidad del tiempo en el ciclo: ordenar + puntero doble, tabla hash
2. Cuando hay varias variables, como a [i] + a [j] == 0, puede corregir j, es decir, encontrar 0 ~ Si existe el número -a [j] en j-1, puede calcular mientras calcula
3. Tabla hash: ¡cuente el número de ocurrencias!
4. Punteros dobles: se pueden considerar los punteros dobles cuando se satisface la monotonicidad

Método común de tabla hash: contar el número de ocurrencias

El hash también sacrifica espacio a cambio de tiempo

242.

Análisis:
use una tabla hash para contar la cantidad de veces que aparece cada carácter y la complejidad del tiempo O(n). La primera vez que lo hice, se ordenó directamente, lo cual era complejo en el tiempo O(nlogn).
Por supuesto, el rango de mapeo de esta pregunta es relativamente pequeño y puede usar una matriz como tabla hash. Si la gama de problemas avanzados es grande, no se deben utilizar matrices.
"Y si el valor hash es relativamente pequeño, particularmente disperso, y el intervalo es muy grande, el uso de matrices provocará una gran pérdida de espacio".

class Solution {
    
    
public:
    bool isAnagram(string s, string t) {
    
    
        // 时间复杂度O(n)
        // 空间复杂度O(26)
        if(s.size() != t.size()) return false;

        unordered_map<char,int> cnt; // 哈希表
        for(auto c : s) cnt[c] ++;

        for(auto c : t){
    
    
            cnt[c] -- ;
        }

        for(auto x : cnt){
    
    
            if(x.second != 0) return false;
        }
        return true;
    }
};

349. Intersección de dos arreglos

Solución 1: Utiliceunordered_set

class Solution {
    
    
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
    
    
        // 时间复杂度O(n)
        unordered_set<int> num, res;
        for(auto c : nums1) num.insert(c); // 把nums1的元素插到unordered_set中
        
        for(auto c : nums2)
            if(num.count(c)) res.insert(c);
        
        vector<int> ans(res.begin(), res.end()); // 赋值
        return ans;
    }
};

Solución 2: Utiliceunordered_map

class Solution {
    
    
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
    
    
        // 哈希表

        unordered_map<int,int> hash;
        for(auto c : nums1) hash[c] ++ ;

        vector<int> res;
        for(auto c : nums2)
        {
    
    
            if(hash[c] > 0 ) res.push_back(c), hash[c] = 0 ;
        }

        return res;
    }
};

202.

Análisis: El
título dice "bucle infinito", lo que significa "en el proceso de suma sum会重复出现, ¡esto es muy importante para resolver el problema!"

class Solution {
    
    
public:
    bool isHappy(int n) {
    
    
        unordered_map<int,int> cnt;
        while(n != 1)
        {
    
    
            cnt[n] ++;
            dfs(n); // 引用改变n的值
            if(cnt[n] > 1) return false; // 只要出现次数大于1,说明循环了
        }

        return true;
    }

    void dfs(int &n)
    {
    
    
        int res = 0;
        while(n > 0){
    
    
            int t = n % 10;
            res += t * t;
            n /= 10;
        }
        n = res;
    }
};

1. la suma de dos números

Análisis:
las estadísticas de una sola vez no son muy buenas, es mejor insertar mientras se busca

class Solution {
    
    
public:
    vector<int> twoSum(vector<int>& nums, int target) {
    
    
        unordered_map<int,int> hash;
        // 边求边插入
        for(int i = 0;i < nums.size();i ++ ){
    
    
            if(hash.count(target - nums[i])) return {
    
    hash[target - nums[i]], i};
            hash[nums[i]] = i;
        }
        return {
    
    -1, -1};
    }
};

454. Suma de cuatro números II

Análisis: Se
observa N = 500que como máximo se pueden enlazar dos matrices. ¡Métodos de manipulación habituales!

class Solution {
    
    
public:
    int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
    
    
        unordered_map<int,int> hash; //  统计 a + b的值出现的次数
        for(int i = 0;i < A.size();i ++ )
            for(int j = 0;j < B.size();j ++)
                hash[A[i] + B[j]] ++;
                
        int res = 0;
        for(int i = 0;i < C.size();i ++ )
            for(int j = 0;j < D.size();j ++)
            {
    
    
                int s = C[i] + D[j];
                if(hash.count(0 - s)) res += hash[0 - s]; // 这里的处理类似 两数之和
            }
        return res;
    }
};

383.

class Solution {
    
    
public:
    bool canConstruct(string r, string m) {
    
    
        // 哈希计数
        unordered_map<char,int> cnt;
        for(auto c : m) cnt[c] ++;

        for(auto c : r){
    
    
            cnt[c] -- ;
            if(cnt[c] < 0) return false; // 字符不够了
        }
        return true;
    }
};

15. La suma de tres números (ordenar + doble puntero)

Análisis: la
tabla hash de clasificación + doble puntero debe deduplicarse y es demasiado difícil de escribir, use sort + puntero doble en su lugar, la complejidad del evento es O (n ^ 2)
para encontrar a [i] + a [l] + a [r ] == 0, puede enumerar a [i]. Debido a la clasificación anterior, debe satisfacerse la monotonicidad. A medida que i se mueve, lyr se moverán monótonamente, por lo que se pueden usar punteros dobles.
去重的常用操作: ¡La dificultad de esta pregunta también es eliminar la duplicación!

while(l < r && nums[l] == nums[l - 1]) l ++ ;
while(l < r && nums[r] == nums[r + 1]) r -- ;
class Solution {
    
    
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
    
    
        vector<vector<int>> res;

        int n = nums.size();
        if(n < 3) return res;
        sort(nums.begin(), nums.end());

        // a[i] + a[l] + a[r] == 0 , 固定a[i]
        for(int i = 0;i < n;i ++ )
        {
    
    
            if(nums[i] > 0) return res; // 直接返回了
            if(i != 0 && nums[i] == nums[i - 1]) continue; // 去重!关键!
            int l = i + 1, r = n - 1;
            while(l < r)
            {
    
    
                if(nums[l] + nums[i] + nums[r] == 0) {
    
    
                    res.push_back({
    
    nums[i], nums[l], nums[r]});
                    l ++ , r -- ;
                    // 去重的常见操作
                    while(l < r && nums[l] == nums[l - 1]) l ++ ;
                    while(l < r && nums[r] == nums[r + 1]) r -- ;
                }else if(nums[l] + nums[i] + nums[r] < 0){
    
    
                    l ++ ;
                }else{
    
    
                    r -- ;
                }
            }
        }
        return res;
    }
};

18. La suma de cuatro números (clasificación + doble puntero, lo mismo que la suma de tres números)

Análisis: complejidad temporal O ( n 3 n ^ {3}norte3 ), ¡más problemático que la adición de cuatro números II en el proceso de deduplicación!
Inserte la descripción de la imagen aquí

class Solution {
    
    
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
    
    
        vector<vector<int>> res;
        int n = nums.size();
        sort(nums.begin(), nums.end());
        for(int i = 0;i < n ; i++ )
            for(int j = i + 1;j < n ;j ++ )
            {
    
    
                // 去重        
                if(i != 0 && nums[i] == nums[i - 1]) break;
                if(j != i + 1 && nums[j] == nums[j - 1]) continue; // 这里是continue 
        
                int l = j + 1,r = n - 1;
                while(l < r)
                {
    
    
                    if(nums[i] + nums[j] + nums[l] + nums[r] == target){
    
    
                        res.push_back({
    
    nums[i], nums[j], nums[l], nums[r]});
                        l ++ ,r -- ;
                        while(l < r && nums[l] == nums[l - 1]) l ++ ;
                        while(l < r && nums[r] == nums[r + 1]) r --; 
                        
                    }else if(nums[i] + nums[j] + nums[l] + nums[r] < target) l ++ ;
                    else r -- ;
                }
            }
        
        return res;
    }
};

Supongo que te gusta

Origin blog.csdn.net/weixin_43154149/article/details/112180592
Recomendado
Clasificación