# Weekly portal There are two more questions, but the supplementary questions in the afternoon are very smooth. It's probably because I slept all afternoon, ha ha ha Idea: hash

Time complexity: O ( n 3 + n ∗ l i m i t ) O(n^3 + n*limit) O(n3+n∗limit), l i m i t limit limit is n u m s nums The value range of num.

With two-dimensional array m a r k mark mark. m a r k i , j mark_{i,j} marki,j ， stored n u m s [ i . . n − 1 ] nums[i..n-1] Within nums[i..n − 1] interval j j Quantity of j.

Available in O ( n ∗ l i m i t ) O(n*limit) O(n * limit) m a r k mark The initialization code of mark is as follows:

int mark = {0};
for (int i = nums.size()-1; i >= 0; i--) {
memcpy(mark[i], mark[i+1], sizeof(mark[i]));
mark[i][nums[i]]++;
}


Next, enumerate the coordinates a , b , c a,b,c a,b,c. Let the cumulative sum of the three elements be s u m sum sum, which can be accumulated m a r k c + 1 , s u m mark_{c+1, sum} Mark C + 1, sum ， get the final answer. The complete code is as follows:

class Solution {
public:
int mark = {0};
for (int i = nums.size()-1; i >= 0; i--) {
memcpy(mark[i], mark[i+1], sizeof(mark[i]));
mark[i][nums[i]]++;
}
int anw = 0;
for (int i = 0; i < nums.size(); i++) {
for (int j = i+1; j < nums.size(); j++) {
for (int k = j+1; k < nums.size(); k++) {
int sum = nums[i] + nums[j] + nums[k];
if (sum <= 100) {
anw += mark[k+1][sum];
}
}
}
}
return anw;
}
};


# 5864. Number of weak characters in the game

Idea: sort, double pointer

Time complexity: O ( n ∗ lg ⁡ n ) O(n*\lg n) O(n∗lgn)

First will p r o p prop prop according to a t t a c k attack attack is sorted in descending order.

After sorting, for p r o p i prop_i propi to quickly determine a t t a c k attack attack higher than p r o p i prop_i The maximum subscript of propi ， is marked as p i p_i pi​. Will interval [ 0 , p i ] [0, p_i] The highest defense in [0,pi] is recorded as d e f i def_i defi​.

If d e f i def_i defi above p r o p i prop_i propi's defense, then p r o p i prop_i propi ， is a weak role, and vice versa.

because p r o p prop prop is a t t a c k attack In descending order of attack, there must be:

• p i − 1 ≤ p i p_{i-1} \le p_i pi−1​≤pi​
• d e f i = m a x ( d e f e n s e p i , d e f i − 1 ) def_i = max(defense_{p_i}, def_{i-1}) defi​=max(defensepi​​,defi−1​)

Therefore, you can O ( n ) O(n) The time complexity of O(n) recursively deduces all p i p_i pi ， and d e f i def_i defi​.

class Solution {
public:
int numberOfWeakCharacters(vector<vector<int>>& p) {
sort(p.begin(), p.end(), [](const auto &l, const auto &r) {
return l > r;
});

int anw = 0;

for (int limit = 0, i = -1, j = 0; j < p.size(); j++) {
while (i+1 < j && p[i+1] != p[j]) {
i++;
limit = max(limit, p[i]);
}
if (limit > p[j]) {
anw++;
}
}
return anw;
}
};


# 5865. The first day after visiting all rooms

Idea: recursion, disassembly

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

Considering that each room has two states:

• Has been accessed an odd number of times
• Has been accessed an even number of times

You might as well use two arrays f 1 f1 f1, f 2 f2 f2 represents the number of days to arrive at the room for the first and second time, respectively.

f 1 i f1_i f1i is easy to calculate: f 1 i = f 2 i − 1 + 1 f1_i = f2_{i-1} + 1 f1i​=f2i−1​+1.

f 2 i f2_i f2i# can be disassembled into three parts:

• First arrival at the room i i i. Time consuming f 1 i f1_i f1i# days.
• from i i i return n e x t i next_i nexti, 1 day.
• from n e x t i next_i nexti ， back again i i i. Time consuming f 1 i − f 1 n e x t i f1_i - f1_{next_i} f1i − f1nexti − days.

The first two parts are easy to understand, no nonsense. Just the third part.

Back in n e x t i next_i After nexti, n e x t i next_i nexti has been accessed an odd number of times, [ n e x t i + 1 , i − 1 ] [next_i+1, i-1] The rooms in [nexti + 1,i − 1] were visited an even number of times.

Not hard to find, [ n e x t i , i − 1 ] [next_i, i-1] The state of the room in [nexti, i − 1] is equivalent to the first arrival n e x t i next_i The state when nexti ， so from n e x t i next_i nexti ， back again i i The time taken for i is f 1 i − f 1 n e x t i f1_i - f1_{next_i} f1i​−f1nexti​​.

in summary:

• f 1 i = f 2 i − 1 + 1 f1_i = f2_{i-1} + 1 f1i​=f2i−1​+1
• f 2 i = f 1 i + 1 + f 1 i − f 1 n e x t i f2_i = f1_{i} + 1 + f1_{i} - f1_{next_i} f2i​=f1i​+1+f1i​−f1nexti​​
class Solution {
public:
int firstDayBeenInAllRooms(vector<int>& next) {
vector<int64_t> f1(next.size());
vector<int64_t> f2(next.size());
f2 = 1;
const int64_t mod = 1e9+7;
for (int i = 1; i < next.size(); i++) {
f1[i] = (f2[i-1] + 1)%mod;
f2[i] = (f1[i] + 1 + (mod+f1[i] - f1[next[i]]))%mod;
}

return f1.back();
}
};


# 5866. Maximum common factor sorting of arrays

Idea: joint search set, prime sieve

Time complexity: O ( n + l i m i t ∗ l i m i t ) O(n+limit*\sqrt {limit}) O(n+limit∗limit ​)， l i m i t limit limit is the value range.

set up p o s i pos_i posi = after sorting n u m s i nums_i The location of numsi ， can be found in O ( l i m i t + n ) O(limit+n) The time complexity of O(limit+n) is obtained, and the code is as follows:

int cnt = {0};
int pos = {0};
// Count the number of occurrences of each array
for (auto n : nums) {
cnt[n]++;
}
// Calculate the prefix and of cnt
for (int i = 1; i <= 100000; i++) {
cnt[i] += cnt[i-1];
}
// The position of each array is obtained by prefix and
for (int i = 0; i < nums.size(); i++) {
pos[i] = --cnt[nums[i]];
}


Now the problem becomes "location" i i Can i reach the position through several transformations p o s i pos_i posi​」.

Consider three locations a a a， b b b， c c c. If a a a and b b b exchangeable, b b b and c c c is exchangeable, then with the help of b b b， a a a and c c c also interchangeable positions. The old fellow who has familiarity with and searched for it should have thought that it can help and check the relationship between the maintenance locations.

With a length of n + l i m i t n+limit Array of n+limit f a fa fa, used to store and query sets:

• front n n n elements represent n u m s nums In nums n n n locations
• after l i m i t limit limit elements represent divisors

Therefore, we can find the prime numbers that can be filtered by enumeration similar to prime sieve p p p is the position of the division, and these positions are compared with n + p n+p n+p merge together.

Finally, enumeration i ∈ [ 0 , n − 1 ] i∈[0,n-1] i ∈ [0,n − 1], with the help of f a fa fa judgment i i i and p o s i pos_i posi# whether it is connected. If all are connected, return t r u e true true, otherwise return f a l s e false false.

class Solution {
public:
int fa = {0};
int find(int x) {
int t = x;
while(t != fa[t]) {
t = fa[t];
}
while(x != fa[x]) {
int tmp = fa[x];
fa[x] = t;
x = tmp;
}
return x;
}
void merge(int u, int v) {
int fu = find(u);
int fv = find(v);
fa[fu] = fv;
}
bool gcdSort(vector<int>& nums) {
int cnt = {0};
int pos = {0};
// Count the number of occurrences of each array
for (auto n : nums) {
cnt[n]++;
}
// Calculate the prefix and of cnt
for (int i = 1; i <= 100000; i++) {
cnt[i] += cnt[i-1];
}
// The position of each array is obtained by prefix and
for (int i = 0; i < nums.size(); i++) {
pos[i] = --cnt[nums[i]];
}

// Initialize and query set
for (int i = 0; i <= 130000; i++) {
fa[i] = i;
}

// Reuse cnt. cnt[i] represents the position where the number I first appears
memset(cnt, -1, sizeof(cnt));

for (int i = 0; i < nums.size(); i++) {
if (cnt[nums[i]] != -1) {
// The same array must be connected and can be merged first
merge(cnt[nums[i]], i);
} else {
// Update cnt
cnt[nums[i]] = i;
}
}

// Prime sieve
bool mark = {0};
for (int i = 2; i <= 100000; i++) {
if (mark[i]) { continue; }
mark[i] = true;
for (int j = i; j <= 100000; j += i) {
// j has appeared in nums. Obviously j is divisible by i.
// So merge j with n+i
if (cnt[j] != -1) {
merge(i+30000, cnt[j]);
}
}
}

// Judge whether I and pos[i] are connected.
for (int i = 0; i < nums.size(); i++) {
if (find(i) != find(pos[i])) {
return false;
}
}

return true;
}
};


Tags: Algorithm leetcode

Posted on Sun, 05 Sep 2021 19:34:12 -0400 by crackerjax