Analyse des idées de résolution de problèmes Leetcode (36) 299-305

  1. Le jeu de devinettes de nombres
    doit être parcouru deux fois, et l'optimisation est que la deuxième fois est liée à la première fois: la table de hachage inclura la première fois
class Solution {
    
    
public:
    string getHint(string secret, string guess) {
    
    
        int x = 0, y = 0;
        string ret;
        unordered_map<char, int> map;
        for (int i = 0; i < guess.size(); i++)
        {
    
    
             if (secret[i] == guess[i])
            {
    
    
                x++;
            } 
            else
            {
    
    
                if (map[secret[i]] > 0) 
                    map[secret[i]]++;
                else 
                    map[secret[i]] = 1;       
            }                    
        }

        for (int i = 0; i < guess.size(); i++)
        {
    
    
            if (map[guess[i]] > 0 && secret[i] != guess[i])
            {
    
    
                map[guess[i]]--;
                y++;
            }
        }

        ret += to_string(x);
        ret += 'A';
        ret += to_string(y);
        ret += 'B';

        return ret;
    }
};

  1. Sous- séquence ascendante la plus longue Étant donné un tableau d'entiers non ordonnés, trouvez la longueur de la sous-séquence ascendante la plus longue.

Il est facile de résoudre avec la programmation dynamique et de comparer le dp précédent à la valeur maximale +1. Cependant, la programmation dynamique a besoin de trouver la valeur maximale à chaque position avant chaque parcours répété, et il est préférable d'utiliser un algorithme gourmand pour le résoudre. L'idée centrale peut être résumée comme suit: maintenir autant que possible une mantisse minimale, de sorte que le plus grand nombre possible de nouveaux nombres puisse être ajouté pour former une sous-séquence plus longue. Par conséquent, à chaque fois, vous n'avez pas besoin de parcourir toutes les positions précédentes, mais de parcourir le tableau d'enregistrements de sous-séquence lui-même, en remplaçant l'ancien élément plus grand que le nouvel élément. Puisque les sous-séquences sont triées, elles peuvent être résolues par dichotomie, optimisant ainsi la complexité temporelle.

class Solution {
    
    
public:
    int lengthOfLIS(vector<int>& nums) {
    
    
        int size = nums.size();
        if (size == 0) return 0;
        vector<int> dp(size, 0);
        int max = 1, dpMax;
        dp[0] = 1;
        for (int i = 1; i < size; i++)
        {
    
    
            dpMax = 1;
            for (int j = 0; j < i; j++)
            {
    
    
                if (nums[i] > nums[j])
                {
    
    
                    if (dp[j] + 1 > dpMax)
                    {
    
    
                        dpMax = dp[j] + 1;
                    }
                }
            }
            dp[i] = dpMax;
            if (dpMax > max)
                max = dpMax;
        }
        return max;
    }
};
class Solution {
    
    
public:
    int lengthOfLIS(vector<int> &nums) {
    
    
        int len = nums.size();
        if (len < 2) {
    
    
            return len;
        }

        vector<int> tail;
        tail.push_back(nums[0]);
        // tail 结尾的那个索引
        int end = 0;

        for (int i = 1; i < len; ++i) 
        {
    
    
            if (nums[i] > tail[end]) 
            {
    
    
                tail.push_back(nums[i]);
                end++;
            } 
            else 
            {
    
    
                int left = 0;
                int right = end;
                while (left < right) 
                {
    
    
                    int mid = (left + right) >> 1;
                    if (tail[mid] < nums[i]) 
                    {
    
    
                        left = mid + 1;
                    } 
                    else 
                    {
    
    
                        right = mid;
                    }
                }
                tail[left] = nums[i];
            }
        }
        return end + 1;
    }
};

  1. Supprimer les crochets non valides
    Supprimez le nombre minimum de crochets non valides pour rendre la chaîne d'entrée valide et renvoyer tous les résultats possibles.

La méthode classique de retour arrière est utilisée pour résoudre des problèmes. Le processus de jugement de la validité de la chaîne est mis dans le processus de traversée profonde, une fois que la chaîne de résultat actuellement obtenue est invalide, il se termine prématurément. L'implémentation spécifique consiste à enregistrer le nombre de mauvais '(' et ')' cntl et cntr dans la chaîne de résultat actuelle. Si cntr> cntl apparaît pendant le processus de parcours, la chaîne de résultat actuelle est invalide et se termine tôt

class Solution {
    
    
public:
    unordered_set<string> sets;

    /*
    * @param s: 源字符串
    * @param index: 当前源字符串索引
    * @param str: 记录结果
    * @param el: 当前可以删除的'('的数量
    * @param er: 当前可以删除的')'的数量
    * @param cntl: 记录当前str中错误的'('的数量
    * @param cntr: 记录当前str中错误的')'的数量
    */
    void dfs(string &s, int index, string &str, int el, int er, int cntl, int cntr){
    
    
        // 剪枝
        if(cntr > cntl || el < 0 || er < 0) return;
        // 结束条件
        if(index == s.length()){
    
    
            if(cntl == 0 && cntr == 0){
    
    
                sets.insert(str);
            }
            return;
        }

        // 当前字符不是括号,直接跳过
        if(s[index] != '(' && s[index] != ')'){
    
    
            str += s[index];
            dfs(s, index+1, str, el, er, cntl, cntr);
            str.erase(str.length()-1, 1);
        }else{
    
    
            // 不删除当前括号,需要记录当前str中错误的左右括号的数量
            str += s[index];
            int cl = cntl, cr = cntr;
            if(s[index] == '(') cl++;
            else{
    
    
                if(cl == 0) cr++;
                else cl--;
            }
            dfs(s, index+1, str, el, er, cl, cr);
            str.erase(str.length()-1, 1);

            // 删除当前括号,修改可删除的左右括号数量
            if(s[index] == '(') --el;
            else --er;
            dfs(s, index+1, str, el, er, cntl, cntr);
        }
    }

    vector<string> removeInvalidParentheses(string s) {
    
    
        vector<string> res;

        // 统计源字符串中无效括号数目
        int el = 0, er = 0;
        for(int i = 0; i < s.length(); ++i){
    
    
            if(s[i] == '(') el++;
            else if(s[i] == ')'){
    
    
                if(el == 0) er++;
                else el--;
            }
        }

        string str = "";
        dfs(s, 0, str, el, er, 0, 0);

        for(auto it = sets.begin(); it != sets.end(); ++it){
    
    
            res.push_back(*it);
        }

        return res;
    }
};

  1. Aire et extraction
    Étant donné un tableau d'entiers nums, trouver la somme des éléments dans la plage de l'indice i à j (i ≤ j), y compris i et j.

Une question très simple, stockez les variables accumulées à l'avance puis soustrayez-les

 class NumArray {
    
    
public:
    NumArray(vector<int>& nums) {
    
    

        int sum = 0;
        for (int i = 0; i < nums.size(); ++i)
        {
    
    
            sum += nums.at(i);
            m_map[i] = sum;
        }
    }

    int sumRange(int i, int j) {
    
    

        return m_map[j] - m_map[i - 1]; // i == 0  key为-1不存在,会自动插入pair(-1, 0)
    }


private:
    unordered_map<int, int> m_map; //<索引,0到索引的元素和>

};



  1. Zone bidimensionnelle et extraction
    À partir d'une matrice bidimensionnelle, calculez la somme des éléments dans sa plage sous-rectangulaire. Le coin supérieur gauche de la sous-matrice est (row1, col1) et le coin inférieur droit est (row2, col2).

Cette question est essentiellement la même que la question précédente: tamponnez la zone de quatre points fixes à 0,0, puis soustrayez-la.

class NumMatrix {
    
    
public:
    NumMatrix(vector<vector<int>>& matrix) {
    
    
        rw = matrix.size();
        cl = rw ?  matrix[0].size() : 0;
        sumMatrix = vector<vector<int>>(rw + 1, vector<int> (cl + 1, 0));
        for (int i = 1; i < rw + 1; ++i){
    
    
            for (int j = 1; j < cl + 1; ++j){
    
    
                sumMatrix[i][j] = matrix[i - 1][j - 1] + 
                sumMatrix[i - 1][j] + sumMatrix[i][j - 1] - sumMatrix[i - 1][j - 1];
            }
        }
    }
    
    int sumRegion(int row1, int col1, int row2, int col2) {
    
            
        return sumMatrix[row2 + 1][col2 + 1] - sumMatrix[row1][col2 + 1] - sumMatrix[row2 + 1][col1] + sumMatrix[row1][col1];
    }
private:
    int rw, cl;
    vector<vector<int>> sumMatrix;
};

/**
 * Your NumMatrix object will be instantiated and called as such:
 * NumMatrix* obj = new NumMatrix(matrix);
 * int param_1 = obj->sumRegion(row1,col1,row2,col2);
 */

  1. Nombre
    cumulatif Le nombre cumulé est une chaîne de caractères et les nombres qui le composent peuvent former une séquence d'accumulation.
    Une séquence d'accumulation valide doit contenir au moins 3 nombres. À l'exception des deux premiers nombres, les autres nombres de la chaîne sont égaux à la somme des deux nombres précédents.
    Étant donné une chaîne contenant uniquement les nombres «0» - «9», écrivez un algorithme pour déterminer si l'entrée donnée est un nombre cumulatif.

** Cette question est une idée typique de retour en arrière. La longueur du parcours n'est que de moitié: si elle est plus longue, le premier nombre qui en est composé ne sera pas la somme du deuxième nombre, qui n'est pas assez long. **

class Solution {
    
    
public:
    bool isAdditiveNumber(string num) {
    
    
        int len = num.size();
        for(int i = 1; i <= len/2; i++){
    
    
            // 为了排除“0235813”
            if(i>1 && num[0]=='0')
                break;
            for(int j = 1; j + i < len;j++){
    
    
                // 这里需要排除第二个数以0开头的情况,dfs里面不需要判断,因为加完的数开始肯定没有0,如果字符串里面有那么找到的位置也不是index3 + len3
                if(!(j>1 && num[i]=='0') && dfs(num,0,i,stol(num.substr(0,i)),i,j,stol(num.substr(i,j)),len))
                    return true;
            }
        }
        return false;
    }
// 当前要加的两个数的索引和长度
    bool dfs(string& num, int index2,int len2,long num2,int index3,int len3,long num3, int &len){
    
    
        // 如果第二个数的索引加上他的长度就等于num的长度,就说明到末尾了,返回true
        if(index3 + len3 == len)
            return true;
        long sum = num2 + num3;
        string sSum = to_string(sum);
        // 将两个数加起来,在剩下的字符串中去寻找这个和,如果在开始的位置就找到,就说明可以继续下去
        if(num.find(sSum,index3+len3)!=index3+len3)
            return false;
        return dfs(num,index3,len3,num3,index3+len3,sSum.size(),sum,len);
    }

};


Je suppose que tu aimes

Origine blog.csdn.net/u013354486/article/details/107837032
conseillé
Classement