Analysis of Leetcode Problem Solving Ideas (36) 299-305

  1. The number guessing game
    needs to be traversed twice, and the optimization is that the second time is related to the first time: the hash table will include the first time
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. Longest ascending subsequence
    Given an unordered integer array, find the length of the longest ascending subsequence.

It is easy to solve with dynamic programming, and compare the previous dp to the maximum value +1. However, dynamic programming needs to find the maximum value at each position before each repeated traversal, and it is better to use a greedy algorithm to solve it. The core idea can be summarized as: maintain a minimum mantissa as much as possible, so that as many new numbers as possible can be added to form a longer subsequence. Therefore, each time you do not need to traverse all the previous positions, but traverse the sub-sequence record array itself, replacing the old element larger than the new element. Since the subsequences are sorted, they can be solved by dichotomy, thereby optimizing the time complexity.

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. Delete invalid brackets
    Delete the minimum number of invalid brackets to make the input string valid and return all possible results.

The classic backtracking method is used to solve problems. The process of judging the validity of the string is put into the deep traversal process, once the result string currently obtained is invalid, it is terminated early. The specific implementation is to record the number of wrong'(' and')' cntl and cntr in the current result string. If cntr> cntl appears during the traversal process, the current result string is invalid and terminated early

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. Region and retrieval
    Given an integer array nums, find the sum of the elements in the range from index i to j (i ≤ j), including i and j.

A very simple question, store the accumulated variables in advance and then subtract them

 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. Two-dimensional area and retrieval
    Given a two-dimensional matrix, calculate the sum of the elements in its sub-rectangular range. The upper left corner of the sub-matrix is ​​(row1, col1) and the lower right corner is (row2, col2).

This question is essentially the same as the previous question: buffer the area of ​​four fixed points to 0,0, and then subtract it.

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. Accumulative number The
    accumulative number is a character string, and the numbers that make up it can form an accumulation sequence.
    A valid accumulation sequence must contain at least 3 numbers. Except for the first two numbers, the other numbers in the string are equal to the sum of the two previous numbers.
    Given a string containing only the numbers '0'-'9', write an algorithm to determine whether the given input is an accumulative number.

**This question is a typical backtracking idea. The length of the traversal is only half: if it is longer, the first number composed of it will not be the sum of the second number, which is not long enough. **

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);
    }

};


Guess you like

Origin blog.csdn.net/u013354486/article/details/107837032