LeetCode kickback week 259

Weekly portal

I came to work in the company. I had a week's competition in my spare time. I asked three questions. I'm very satisfied. Ha ha ha.

2011. Variable value after operation

Time complexity: O ( n ) O(n) O(n)

I've worked out a simple problem. The cumulative sum can be calculated according to the middle symbol of each operation.

class Solution {
public:
    int finalValueAfterOperations(vector<string>& operations) {
        int anw = 0; 
        for (const auto &s : operations) {
            anw += (s[1] == '+' ? 1 : -1);
        }
        return anw;
    }
};

2012. Sum of array values

Idea: pretreatment

Time complexity: O ( n ) O(n) O(n)

With one-dimensional array s u f suf suf, s u f i suf_i sufi + n u m s i nums_i numsi is the minimum value in the suffix starting from.

You can enumerate from large to small i i i, O ( n ) O(n) O(n) pretreatment of all s u f i suf_i sufi​:
s u f i = m i n ( n u m s i , s u f i + 1 ) suf_i = min(nums_i, suf_{i+1}) sufi​=min(numsi​,sufi+1​)

Similarly, there is a one-dimensional array p r e pre pre, p r e i pre_i prei , denotes n u m s i nums_i numsi is the maximum value in the prefix of the end point. Enumeration from small to large i i i, O ( n ) O(n) O(n) pretreatment of all p r e i pre_i prei​:
p r e i = m a x ( n u m s i , p r e i − 1 ) pre_i = max(nums_i, pre_{i-1}) prei​=max(numsi​,prei−1​)

At this point, the beauty value of each location can be O ( 1 ) O(1) The of O(1) is obtained:

  • If p r e i − 1 < n u m s i < s u f i + 1 pre_{i-1} \lt nums_i \lt suf_{i+1} If prei − 1 < numsi < Sufi + 1, the beauty value is 2.
  • If the above conditions are not met, and n u m s i − 1 ≤ n u m s i < n u m s i + 1 nums_{i-1} \le nums_i \lt nums_{i+1} Numsi − 1 ≤ numsi < numsi + 1, then the beauty value is 1.
  • Other cases are 0.
class Solution {
public:
    int sumOfBeauties(vector<int>& nums) {
        vector<int> suf(nums.size(), nums.back());
        for (int i = nums.size()-2; i >= 0; i--) {
            suf[i] = min(suf[i+1], nums[i]);
        }
        vector<int> pre(nums.size(), nums[0]);
        for (int i = 1; i < nums.size(); i++) {
            pre[i] = max(pre[i-1], nums[i]);
        }
        int sum = 0;
        for (int i = 1; i <= nums.size()-2; i++) {
            if (pre[i-1] < nums[i] && nums[i] < suf[i+1]) {
                sum += 2;
            } else if (nums[i-1] < nums[i] && nums[i] < nums[i+1]) {
                sum += 1;
            }
        }
        return sum;
    }
};

2013. Test results

Idea: hash, diagonal

Time complexity: O ( a d d ∗ c o u n t ) O(add*count) O(add∗count)

There is a container m a r k mark mark, used to record the coordinates as ( x , y ) (x,y) The number of occurrences of the point of (x,y).

For each a d d ( x , y ) add(x,y) add(x,y) operation, just execute m a r k ( x , y ) + + mark(x,y)\mathrel{+}\mathrel{+} mark(x,y)++.

For each c o u n t ( x , y ) count(x,y) count(x,y) operation, you can enumerate all the coordinates that have occurred ( x 0 , y 0 ) (x_0,y_0) (x0, y0) to judge whether they can form the diagonal of a square, which meets the following two requirements:

  • a b s ( x − x 0 ) = a b s ( y − y 0 ) abs(x-x_0) = abs(y-y_0) abs(x−x0​)=abs(y−y0​)
  • x ≠ x 0 x \ne x_0 x​=x0​, y ≠ y 0 y \ne y_0 y​=y0​

If the above requirements are met, the coordinates of the other two points of the square can be calculated:

  • x 1 = x , y 1 = y 0 x_1 = x, y_1 = y_0 x1​=x,y1​=y0​
  • x 2 = x 0 , y 2 = y x_2 = x_0, y_2 = y x2​=x0​,y2​=y

When you get the four coordinates, from m a r k mark Found in mark ( x 0 , y 0 ) (x_0,y_0) (x0​,y0​), ( x 1 , y 1 ) (x_1,y_1) (x1​,y1​), ( x 2 , y 2 ) (x_2,y_2) (x2, y2) the number of points on the three coordinates is recorded as c 0 , c 1 , c 2 c_0,c_1,c_2 c0​,c1​,c2​.

accumulation c 0 ∗ c 1 ∗ c 2 c_0*c_1*c_2 c0 * c1 * c2 is this time c o u n t ( x , y ) count(x,y) The answer to the count(x,y) operation.

class DetectSquares {
public:
    // Define the container mark, where key is the coordinate and value is the number of occurrences.
    // The first 32 bits of the key store x and the last 32 bits store y. In this way, there is no need to define hash and operator = =
    unordered_map<uint64_t, int> mark;

    DetectSquares() {
    }
    
    void add(vector<int> point) {
        // Number of occurrences of update point
        mark[uint64_t(point[0])<<32|point[1]]++;
    }
    
    int count(const vector<int> &point) {
        int x = point[0], y = point[1];
        int anw = 0; // anw is used to store the answers of this query

        // Enumerate all occurrences
        for (const auto &p : mark) {
            int x0 = (p.first>>32), y0 = p.first&0xffff;
            // Judge that (x,y) and (x0,y0) can form the diagonal of a square.
            if (x == x0 || y == y0) continue;
            if (abs(x-x0) != abs(y-y0)) continue;

            int x1 = x, y1 = y0;
            int x2 = x0, y2 = y;
            auto it1 = mark.find(uint64_t(x1)<<32|y1);
            auto it2 = mark.find(uint64_t(x2)<<32|y2);
            // Judge whether the other two points exist.
            if (it1 != mark.end() && it2 != mark.end()) {
                // Cumulative c0*c1*c2
                anw += it1->second * it2->second * p.second;
            }
        }
        return anw;
    }
};

/**
 * Your DetectSquares object will be instantiated and called as such:
 * DetectSquares* obj = new DetectSquares();
 * obj->add(point);
 * int param_2 = obj->count(point);
 */

2014. Longest subsequence repeated K times

Idea: Full Permutation, enumerating subsets, pruning

Time complexity: O ( n ∗ r ! ∗ 2 r ) O(n*r!*2^r) O(n∗r!∗2r). n n n is the length of the input string, r r r is the upper limit of the length of the answer.

First, we will appear more than once k k Find the character of k and record it as a set r e m a i n remain remain.

Every occurrence of the same character k k Join k times r e m a i n remain remain once, so as to facilitate the processing of repeated characters in the sequence.

Consider the length of the input string n ∈ [ 2 , k ∗ 8 ) n\in[2,k*8) n ∈ [2,k * 8). Therefore, r e m a i n remain There must be no more than 7 elements in remain.

Violence enumeration r e m a i n remain All permutations of all subsets of remain p p p. About 7 ! ∗ 2 7 7!*2^7 7! * 27 kinds. For each kind p p p check that it is s s The number of occurrences in s. the overall time complexity is O ( n ∗ r ! ∗ 2 r ) O(n*r!*2^r) O(n * r! * 2r). Approx 1 e 9 1e9 1e9, it must timeout. Here is a pruning strategy.

Consider permutation p p p in s s The number of occurrences in s is less than k k k. Then all p p The permutations with p as the prefix can not be candidate answers, so there is no need to enumerate these permutations.

Consider appearing k k k times, length r ∈ [ 1 , 7 ] r\in[1,7] The subsequences of r ∈ [1,7] are C 7 r ∗ 2 r C_7^r*2^r C7r * 2r species, about 3 r 3^r 3r species. Therefore, after adding pruning, it will only be processed 3 r 3^r 3r effective permutations. Other permutations will be filtered because a short prefix does not appear. Therefore, the lower limit of time complexity is reduced to O ( 3 r ∗ n ) O(3^r*n) O(3r * n), as for the upper limit, I didn't think how to estimate it 🙁. . .

class Solution {
public:
    int k_ = 0;
    bool check(const std::string &input, const std::string &tmp) {
        int i = 0, j = 0, k =0;
        for (; j < input.size(); j++) {
            if (tmp[i] == input[j]) {
                i++;
                if (i == tmp.size()) {
                    i = 0;
                    k++;
                }
            }
        }
        return k >= k_;
    }
    /*
    * part String constructed during recursion
    * pos It's time to deal with remain[pos]
    * remain Preprocessed character set
    * input Input string s
    * anw Used to store answers
    */
    void cst(std::string part, int pos, const std::string &remain, const std::string &input, std::string &anw) {
        // Recursive boundary
        if (pos == remain.size()) { return; }

        // If all the remaining characters are added to part and its length is still less than anw, there is no need to deal with it.
        if (part.size() + remain.size()-pos < anw.size()) { return; }

        // Enter the current character into part
        {
            auto tmp = part;
            tmp += remain[pos];
            do {
                // Check whether the characters in tmp exceed k
                if (check(input, tmp)) {
                    // Try updating your answers
                    if (tmp.size() > anw.size() || (tmp.size() == anw.size() && tmp > anw)) {
                        anw = tmp;
                    }
                    // tmp appears k times. Try adding other characters.
                    cst(tmp, pos+1, remain, input, anw);
                }
            } while(std::next_permutation(tmp.begin(), tmp.end()));
        }

        // The current character is not added to part.
        {
            cst(part, pos+1, remain, input, anw);
        }
    }

    string longestSubsequenceRepeatedK(string s, int k) {
        k_ = k; // Copy k to the member function for easy processing
        std::string remain; // A character set that appears at least k times
        unordered_map<char, int> count; // Used to count the number of occurrences of each character.
        
        // Statistical times
        for (auto c : s) {
            count[c]++;
        }

        // Initialize retain. Add retain once every k occurrences of the character.
        for (auto &p : count) { 
            while (p.second >= k) {
                p.second -= k;
                remain += p.first;
            }
        }
        // Sorting is to use std::next_permutation
        sort(remain.begin(), remain.end());

        std::string anw; // Used to store answers
        cst("", 0, remain, s, anw); // Enumerate all permutations and find answers

        return anw;
    }
};

Tags: Java Algorithm leetcode

Posted on Mon, 20 Sep 2021 15:46:55 -0400 by devang23