LeetCode Weekly Competition 260

[Weekly Portal]https://leetcode-cn.com/contest/weekly-contest-260/

2016.Maximum difference between incremental elements

Idea: Enumeration of Violence

Time Complexity: O ( n 2 ) O(n^2) O(n2)

First, the most straightforward way to enumerate all subscript pairs ( i , j ) (i,j) (i,j), judgment n u m s i nums_i numsi and n u m s j nums_j Size of numsj and update the answer.

class Solution {
public:
    int maximumDifference(vector<int>& nums) {
        int anw = -1; // Answer initialized to -1
        for (int i = 0; i < nums.size(); i++) {
            for (int j = i+1; j < nums.size(); j++) {
                if (nums[i] < nums[j]) {
                	// Find a pair of subscripts that match the requirements and try to update the answer
                    anw = max(anw, nums[j] - nums[i]);
                }
            }
        }
        return anw;
    }
};

Idea: Preprocessing Minimum

Time Complexity: O ( n ) O(n) O(n)

Set length to n n One-dimensional array of n o p t opt opt, o p t i opt_i opti means before i i The minimum of the i elements. Then for each n u m s i , i ≥ 1 nums_i,i \ge 1 numsi, i < or > 1, the maximum difference that can be contributed is:

  • When o p t i − 1 ≤ n u m s i opt_{i-1} \le nums_i When opti_1 < numsi, is n u m s i − o p t i − 1 nums_i - opt_{i-1} numsi​−opti−1​
  • Conversely, -1.

As a whole, you can start with O ( n ) O(n) Preprocessing of O(n) o p t opt opt. Then O ( n ) O(n) Find each of O(n) n u m s i nums_i The maximum difference of numsi, the largest of which is the answer.

class Solution {
public:
    int maximumDifference(vector<int>& nums) {
        int anw = -1; 
        // Because only opt[i-1] is concerned, opt can be reduced to a variable.
        for (int i = 1, opt = nums[0]; i < nums.size(); i++) {
            if(opt < nums[i]) {
                anw = max(anw, nums[i] - opt);
            }
            opt = min(opt, nums[i]);
        }
        return anw;
    }
};

2017.Grid Game

Thought: Greed

Time Complexity: O ( n ) O(n) O(n)

It's not hard to find, first hand must walk by n + 1 n+1 n+1 grid. First hand has n n n walks, choose a location p p p, p ∈ [ 0 , n ) p\in[0,n) p < [0, n], first hand will go through the first row [ 0 , p ] [0,p] [0, p], and the second row [ p , n ) [p, n) [p,n).

There are two options for the latter:

  • ( 0 , 0 ) → ( 0 , n − 1 ) → ( 1 , n − 1 ) (0,0)→(0,n-1)→(1,n-1) (0,0)(0,n_1)(1,n_1), with the score in the first row ( p , n ) (p,n) (p,n) the sum of the lattices.
  • ( 0 , 0 ) → ( 1 , n − 1 ) → ( 1 , n − 1 ) (0,0)→(1,n-1)→(1,n-1) (0,0)(1,n_1)(1,n_1), with a score in second place [ 0 , p ) [0,p) The sum of the lattices.

It's not difficult to come up with a first-hand strategy, choose one p p p, so that the first row ( p , n ) (p,n) (p,n) and Row 2 [ 0 , p ) [0,p) The maximum value in [0, p] is the smallest.

class Solution {
public:
    long long gridGame(vector<vector<int>>& grid) {
        int64_t sum[2] = {0};
        int n = grid[0].size();
        for (int i = 0; i < n; i++) {
            sum[0] += grid[0][i]; // Calculate the sum of the first row
            sum[1] += grid[1][i]; // Calculate the sum of the second row
        }
        int64_t pre[100000] = {grid[0][0]};
        for (int i = 1; i < n; i++) {
            pre[i] = pre[i-1] + grid[0][i]; // Calculate the prefix and sum of the first row
        }
        // anw is the final answer, initialized to a maximum.
        int64_t anw = sum[0] + sum[1];
        // suf is the suffix sum of the second row, simplified as a variable
        int suf = 0;
        for (int i = n-1; i >= 0; i--) {
            suf += grid[1][i];// Calculate Suffix and
            // opt: The next best solution when p = i is chosen first.
            int opt = max(sum[0] - pre[i], sum[1] - suf);
            // anw holds the smallest "back-hand optimal solution".
            anw = min(anw, opt);
        }
        return anw;
    }
};

2018. Determine if a word can be put in a crossword game

Idea Violence Enumeration

Time Complexity: O ( ( n m ) 3 / 2 ) O((nm)^{3/2}) O((nm)3/2)

Enumerated coordinates ( i , j ) (i,j) (i,j), check the four directions:

  • ( i , j ) → ( i + k − 1 , j ) (i,j) → (i+k-1,j) (i,j)→(i+k−1,j)
  • ( i , j ) → ( i − k + 1 , j ) (i,j) → (i-k+1,j) (i,j)→(i−k+1,j)
  • ( i , j ) → ( i , j + k − 1 ) (i,j) → (i,j+k-1) (i,j)→(i,j+k−1)
  • ( i , j ) → ( i , j − k + 1 ) (i,j) → (i,j-k+1) (i,j)→(i,j−k+1)

Is there a direction to drop w o r d s words words, where k k k is w o r d s words The length of words.

In addition, you need to check that the corresponding boundaries meet the requirements.

The overall time complexity is O ( n m k ) O(nmk) O(nmk), considering k k The value of k does not exceed ( n , m ) \sqrt{(n,m)} (n,m) Therefore, the time complexity can be simplified to O ( ( n m ) 3 / 2 ) O((nm)^{3/2}) O((nm)3/2).

class Solution {
  public:
    bool check(int x, int y, const vector<vector<char>> &board, int n, int m) {
        // (x,y) inside the board and #
        if (0 <= x && x < n && 0 <= y && y < m && board[x][y] == '#') {
            return true;
        }
        // Located outside the boundary
        if (-1 == x || x == n || -1 == y || y == m) {
            return true;
        }
        return false;
    }
    bool placeWordInCrossword(vector<vector<char>>& board, string word) {
      int n = board.size(); // Number of rows
      int m = board[0].size(); // Number of columns
      int dx[4] = {-1, 1, 0, 0}; // Define Direction Array
      int dy[4] = {0 , 0, 1,-1};

      // Two-level for loop enumeration starting point (i,j)
      for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
          // Enumeration Direction
          for (int d = 0; d < 4; d++) {
            int sx = i - dx[d];
            int sy = j - dy[d];
            // Check endpoints (sx,sy);
            if (!check(sx, sy, board, n, m)) {
                continue;
            }
            
            int ex = i + (word.size())*dx[d];
            int ey = j + (word.size())*dy[d];
            // Check the endpoint (ex,ey);
            if (!check(ex, ey, board, n, m)) {
                continue;
            }

            // Both endpoints meet the requirements and continue to check other locations.
            bool flag = true;
            for (int k = 0, x = i, y = j; k < word.size() && flag; k++, x += dx[d], y += dy[d]) {
              if (!(board[x][y] == ' ' || board[x][y] == word[k])) {
                  flag = false;
              }
            }
            if (flag) { return flag; }
          }
        }
      }
      return false;
    }
};

2019.The student's score for solving mathematical expressions

Ideas: Dynamic Planning

Time Complexity: O ( n 2 ∗ m 2 + k ) O(n^2*m^2 + k) O(n2∗m2+k). n n n is the length of the string. m m m is the upper limit, and this question is 1000. k k k is the number of answers submitted.

The idea of calculating the correct values is simple, and stacks can be used to multiply and then add.

    int getCorrect(const std::string &s) {
        stack<int> st;
        // Put the first number in first.
        st.push(s[0]-'0');

        // Enumeration Operational Symbols
        for (int i = 1; i < s.size(); i += 2) {
            if (s[i] == '*') {
                // Is the multiplication sign, the next number is multiplied by the top element of the stack
                st.top() *= s[i+1]-'0';
            } else {
                // Is a plus sign, the next number goes to the top of the stack
                st.push(s[i+1]-'0');
            }
        }
        int sum = 0;
        // Numbers in the stack need to be summed.
        while (!st.empty()) {
            sum += st.top();
            st.pop();
        }
        return sum;
    }

The result of the random execution can be solved by dynamic programming. A two-dimensional array is provided. d p dp dp. d p l , r dp_{l,r} dpl,r is a set that represents an expression s l , r s_{l,r} sl,r The collection of execution results in random order.

Divide an expression into two by enumerating operators, such as s l , r s_{l,r} sl,r, and operators s p s_p sp, the expression is divided into s l , p − 1 s_{l,p-1} sl,p_1, and s p + 1 , r s_{p+1,r} sp+1,r​.

It is not difficult to think of a state transfer equation:

  • When l = r l = r When l=r:
    d p l , r = s l dp_{l,r} = s_l dpl,r​=sl​
  • When l ≠ r l\ne r When l=r:
    d p l , r = x ⋅ y , x ∈ d p l , p − 1 , y ∈ d p p + 1 , r dp_{l,r} = x · y, x\in dp_{l,p-1}, y\in dp_{p+1,r} dpl,r​=x⋅y,x∈dpl,p−1​,y∈dpp+1,r​

Therefore, the O ( n 2 ∗ m 2 ) O(n^2*m^2) Find all within O(n2_m2) time complexity d p l , r dp_{l,r} dpl,r​. n n n is the length of the string. m m m is the upper limit, and this question is 1000.

Finally, enumerate the submitted answers and solve the total score.

class Solution {
public:
    int getCorrect(const std::string &s) {
        stack<int> st;
        // Put the first number in first.
        st.push(s[0]-'0');

        // Enumeration Operational Symbols
        for (int i = 1; i < s.size(); i += 2) {
            if (s[i] == '*') {
                // Is the multiplication sign, the next number is multiplied by the top element of the stack
                st.top() *= s[i+1]-'0';
            } else {
                // Is a plus sign, the next number goes to the top of the stack
                st.push(s[i+1]-'0');
            }
        }
        int sum = 0;
        // Numbers in the stack need to be summed.
        while (!st.empty()) {
            sum += st.top();
            st.pop();
        }
        return sum;
    }

    // dp[l][r] represents a set of possible values for the subexpression s[l:r]
    unordered_set<int> dp[32][32];

    void getPossible(const std::string &s, int l, int r) {
        if (dp[l][r].size()) {
            // Calculated, no need to repeat calculation. Return directly
            return;
        }

        if (l == r) {
            // A subexpression of length 1 must contain a number.
            dp[l][r].insert(s[l]-'0');
            return;
        }

        // Enumerate the operation symbols and divide them into two subexpressions.
        for (int i = l+1; i < r; i += 2) {
            getPossible(s, l, i-1); // Calculates the subexpression s[l,i-1]
            getPossible(s, i+1, r); // Compute subexpression s[i+1,r]
            
            // The value of s[l,r] is calculated from the set of two subexpressions.
            for (auto vl : dp[l][i-1]) {
                for (auto vr : dp[i+1][r]) {
                    auto v = ((s[i] == '+') ? (vl + vr) : (vl * vr));
                    if (v <= 1000) {
                        dp[l][r].insert(v);
                    }
                }
            }
        }
    }

    int scoreOfStudents(string s, vector<int>& answers) {
        // Calculate the correct value first
        int correct = getCorrect(s);

        // Potential values from a calculation priority error
        int n = s.size()-1;
        getPossible(s, 0, n);

        // Cumulative total score
        int anw = 0;
        for (auto a : answers) {
            if (a == correct) {
                anw +=5;
            } else if(dp[0][n].count(a) == 1) {
                anw += 2;
            }
        }
        return anw;
    }
};

Tags: Algorithm leetcode

Posted on Thu, 30 Sep 2021 13:51:03 -0400 by frANZi