# 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; 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 = {0};
int n = grid.size();
for (int i = 0; i < n; i++) {
sum += grid[i]; // Calculate the sum of the first row
sum += grid[i]; // Calculate the sum of the second row
}
int64_t pre = {grid};
for (int i = 1; i < n; i++) {
pre[i] = pre[i-1] + grid[i]; // Calculate the prefix and sum of the first row
}
// anw is the final answer, initialized to a maximum.
int64_t anw = sum + sum;
// 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[i];// Calculate Suffix and
// opt: The next best solution when p = i is chosen first.
int opt = max(sum - pre[i], sum - 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.size(); // Number of columns
int dx = {-1, 1, 0, 0}; // Define Direction Array
int dy = {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');

// 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');

// 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;

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[n].count(a) == 1) {
anw += 2;
}
}
return anw;
}
};


Tags: Algorithm leetcode

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