# Learning algorithm idea I

Posted by scheols on Sun, 06 Mar 2022 15:29:05 +0100

Bank robbery days – 2100 – medium

This problem uses the idea of prefix and

For convenience, let nn be the length of securitysecurity.

According to the definition of "days suitable for bank robbery" in the question, first of all, we can determine that the answer falls within the range of [time, n - time)[time,n − time]. In addition, it is stipulated that the left and right sides of "days suitable for bank robbery" need to meet the characteristics of "non increasing" and "non decreasing".

Firstly, we can preprocess the G array. g[i] represents the size relationship between the current time security[i] and the previous time security[i - 1]. When security[i] > security[i - 1], g[i] = 1g[i]=1, when security[i] < security[i - 1], g[i] = -1, otherwise g[i] = 0. In addition, we have the boundary case of g[0] = 0. Then we respond to g

Use the idea of [prefix and]: use array a to record the number of prefixes 1 and array b to record the number of Prefixes - 1. Finally, if i is a suitable day for bank robbery, then time < = i < n - time is satisfied, and the number of (i - time,i] (i − time,i] range prefix 1 is 0, and the number of (i, i + time](i,i+time] range prefix - 1 is 0. C:

```int* goodDaysToRobBank(int* security, int securitySize, int time, int* returnSize) {
int * left = (int *)malloc(sizeof(int) * securitySize);
int * right = (int *)malloc(sizeof(int) * securitySize);
memset(left, 0, sizeof(int) * securitySize);
memset(right, 0, sizeof(int) * securitySize);
for (int i = 1; i < securitySize; i++) {
if (security[i] <= security[i - 1]) {
left[i] = left[i - 1] + 1;
}
if (security[securitySize - i - 1] <= security[securitySize - i]) {
right[securitySize - i - 1] = right[securitySize - i] + 1;
}
}//According to the topic statistics, the prefixes that match

int * ans = (int *)malloc(sizeof(int) * securitySize);
int pos = 0;
for (int i = time; i < securitySize - time; i++) {
if (left[i] >= time && right[i] >= time) {
ans[pos++] = i;
}
}
free(left);
free(right);
*returnSize = pos;
return ans;
}
```

Different palindrome subsequences of length three – 1930 – medium

We can enumerate the types of characters on both sides of the palindrome sequence. For each character, if it appears in the string ss, we record the subscript l for the first time and the subscript r for the last time. Then, taking this character as the palindrome subsequence on both sides, the character in the middle can only be selected in s[l+1... r-1]; The number of palindromes on both sides of the sequence is R + 1.

We traverse the s[l+1... r-1] substring and calculate the number of characters in the substring. When traversing, we can use the hash set to maintain the character types in the substring; When the traversal is completed, the number of elements in the hash set is the total number of characters in the substring.

When enumerating the types of characters on both sides, we maintain the sum of the types of palindrome subsequences and finally return them as answers. C++:

```class Solution {
public:
int countPalindromicSubsequence(string s) {
int n = s.size();
int res = 0;
// Enumeration of characters on both sides
for (char ch = 'a'; ch <= 'z'; ++ch){
int l = 0, r = n - 1;
// Find the subscript of the character for the first time
while (l < n && s[l] != ch){
++l;
}
// Looks for the subscript of the last occurrence of the character
while (r >= 0 && s[r] != ch){
--r;
}
if (r - l < 2){
// The character does not appear or the substring between two subscripts does not exist
continue;
}
// Use the hash set to count the total number of characters of s[l+1..r-1] substring and update the answer
unordered_set<char> charset;
for (int k = l + 1; k < r; ++k){
charset.insert(s[k]);
}
res += charset.size();
}
return res;
}
};
```

Add up – 258 – simple

The most intuitive method is to simulate the process of adding each bit until the remaining number is a single digit.

The way to add the bits of an integer is to calculate the remainder of the current integer divided by 10 each time to get the lowest digit, add the lowest digit to the sum, and then divide the current integer by 10. Repeat the above operation until the current integer becomes 0. At this time, the sum is the result of the addition of each bit of the original integer. C:

```int addDigits(int num){
while (num >= 10) {
int sum = 0;
while (num > 0) {
sum += num % 10;
num /= 10;
}
num = sum;
}
return num;
}
```

Plus one – 66 – simple

When we add one to the array \ textit{digits}digits, we only need to pay attention to how many 9's appear at the end of \ textit{digits}digits. We can consider the following three situations:

If there is no 9 at the end of \ textit{digits}digits, such as [1,2,3] [1,2,3], we directly add one to the end to get [1,2,4] [1,2,4] and return it;

If there are several 9s at the end of \ textit{digits}digits, such as [1, 2, 3, 9, 9] [1,2,3,9,9], we only need to find the first element that is not 9 from the end, that is, 3, and add one to get [1, 2, 4, 9, 9] [1,2,4,9,9]. Then set all 99 at the end to zero, get [1, 2, 4, 0, 0] [1,2,4,0,0] and return.

If all elements of \ textit{digits}digits are 9, such as [9, 9, 9, 9, 9] [9,9,9,9,9,9], the answer is [1, 0, 0, 0, 0] [1,0,0,0,0,0]. We only need to construct a new array with a length of 1 more than \ textit{digits}digits, and set the first element to 1 and the other elements to 0.

We only need to traverse the array \ textit{digits}digits in reverse order once, find the first element that is not 9, add it together, and set all subsequent elements to zero. If all elements in \ textit{digits}digits are 9, we need to return a new array corresponding to the third case in the "thinking" section.

C++:

```class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
int n = digits.size();
for (int i = n - 1; i >= 0; --i) {
if (digits[i] != 9) {
++digits[i];
for (int j = i + 1; j < n; ++j) {
digits[j] = 0;
}
return digits;
}
}

// All elements in digits are 9
vector<int> ans(n + 1);
ans[0] = 1;
return ans;
}
};
```

Valid parentheses – 20 – simple

Judging the validity of parentheses can be solved by using the data structure of "stack".

We traverse the given string s. When we encounter a left parenthesis, we expect a right parenthesis of the same type to close it in subsequent iterations. Since the left parenthesis encountered later must be closed first, we can put this left parenthesis at the top of the stack.

When we encounter a closing bracket, we need to close an opening bracket of the same type. At this point, we can take out the left parentheses at the top of the stack and judge whether they are the same type of parentheses. If it is not the same type, or there is no open bracket in the stack, the string ss is invalid and \ text{False}False is returned. In order to quickly determine the type of brackets, we can use a hash table to store each bracket. The key of the hash table is the right parenthesis, and the value is the left parenthesis of the same type.

After traversal, if there is no left parenthesis in the stack, it means that we close all the left parentheses in the string s and return \ text{True}True. Otherwise, we return \ text{False}False.

Note that the length of the valid string must be even, so if the length of the string is odd, we can directly return \ text{False}False, eliminating the subsequent traversal judgment process. C:

```char pairs(char a) {
if (a == '}') return '{';
if (a == ']') return '[';
if (a == ')') return '(';
return 0;
}

bool isValid(char* s) {
int n = strlen(s);
if (n % 2 == 1) {
return false;
}
int stk[n + 1], top = 0;
for (int i = 0; i < n; i++) {
char ch = pairs(s[i]);
if (ch) {
if (top == 0 || stk[top - 1] != ch) {
return false;
}
top--;
} else {
stk[top++] = s[i];
}
}