Day 7 of Code Random Recording Algorithm Training Camp|454. Addition of Four Numbers II, 383. Ransom Letter, 15. Sum of Three Numbers, 18. Sum of Four Numbers

Links to Articles and Videos Learned Today

454 article link: link
454 video explanation link: link
383 article link: link
383 video explanation
15 article link: link
15 video explanation link: link
18 article link: link
18 video explanation link: link

Problem 454. Adding Four Numbers II

See the title first thought

Title description : Given you four integer arrays nums1, nums2, nums3 and nums4, the length of the arrays is n, please calculate how many tuples (i, j, k, l) can satisfy:

0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

Problem-solving idea : There is no need to consider deduplication when adding four numbers, so I think of using a hash table to deal with this problem.
We not only need to record the appearance of a + b in the set, but also count how many times a + b has appeared, and then we can make a mapping with c + d. So we not only need to count whether it has appeared, but also count the number of times it has appeared. So we choose to use map , use the key to store whether it has appeared, and the value to store the number of times it has appeared.

Thoughts after reading the code caprice

Problem-solving steps:

  1. First define an unordered_map, the key puts the sum of a and b, and the value puts the number of occurrences of the sum of a and b.
  2. Traverse the nums1 and nums2 arrays, count the sum of the elements of the two arrays, and the number of occurrences, and put them in the map.
  3. Define the int variable count to count the number of occurrences of a+b+c+d = 0.
  4. Then traverse the nums3 and nums4 arrays and find that if 0-(c+d) has appeared in the map, use count to count the value corresponding to the key in the map, that is, the number of occurrences.
  5. Finally returns the statistical value count.

Difficulties Encountered During Implementation

At the beginning, I thought of traversing an array first, and then traversing whether the other three arrays appeared in the corresponding collection. In this way, when traversing the next three arrays, the time complexity is O( n 3 n^3n3 ),and the time complexity of traversing the first two arrays first, and then traversing the last two arrays isO (n 2 ) O (n^2)O n2

the code

class Solution {
    
    
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
    
    
        unordered_map<int, int> umap; //key:a+b的数值,value:a+b数值出现的次数
        // 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中
        for (int a : nums1) {
    
    
            for (int b : nums2) {
    
    
                umap[a + b]++;
            }
        }
        int count = 0; // 统计a+b+c+d = 0 出现的次数
        // 在遍历nums3和nums4数组,找到如果 0-(c+d) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。
        for (int c : nums3) {
    
    
            for (int d : nums4) {
    
    
                if (umap.find(0 - (c + d)) != umap.end()) {
    
    
                    count += umap[0 - (c + d)];
                }
            }
        }
        return count;
    }
};

383. Ransom letter

See the title first thought

Title description : Given you two strings: ransomNote and magazine, judge whether ransomNote can be composed of characters in magazine.

Returns true if it can; otherwise returns false.

Each character in magazine can only be used once in ransomNote.

Problem-solving idea : I found that this question is similar to the previous 242. Effective anagrams , but this question is to find out whether string a can form string b, regardless of whether string b can form string a .

Thoughts after reading the code caprice

Two points should be paid attention to when judging whether the first string ransom can be composed of the characters in the second string magazines:

  • Point 1 "Each character in magazine can only be used once in ransomNote"
  • The second point ransomNote and magazine are composed of lowercase English letters

Because this topic only has lowercase letters, an array with a length of 26 is used to record the number of times letters appear in the magazine.

Then use ransomNote to verify that this array contains all the letters required by ransomNote.

Use hashing to solve this problem.

Difficulties Encountered During Implementation

I thought about using map, but I feel a bit overkill. After reading the code, I learned that in the case of this question, the space consumption of using map is larger than that of array, because map needs to maintain red-black tree or hash table, and also Doing a hash function is time-consuming! If the amount of data is large, the difference can be reflected. So arrays are simpler, more direct and more efficient!

the code

class Solution {
    
    
public:
    bool isAnagram(string s, string t) {
    
    
        int record[26]={
    
    0};
        for(int i = 0;i < s.size();i++){
    
    
            record[s[i] - 'a']++;
        }
        for(int i = 0;i < t.size();i++){
    
    
            record[t[i] - 'a']--;
        }
        for(int i = 0;i < 26;i++){
    
    
            if(record[i] != 0){
    
    
                return false;
            }
        }
        return true;
    }
};

Problem 15. The sum of three numbers

See the title first thought

Title description :
Given you an array nums containing n integers, determine whether there are three elements a, b, c in nums, so that a + b + c = 0? Please find all triples that satisfy the condition and are not repeated.

Note: Answers cannot contain repeated triplets.

Problem-solving idea : I still want to use the hash method to solve this problem, but the title requires us to deduplicate, but the idea of ​​deduplication is not very clear.

Thoughts after reading the code caprice

Two solutions are given in Caprice : hash method and double pointer method .

hashing

First use two layers of for loops to determine a + b, and then use hashing to determine whether 0-(a+b) has appeared in the array.

But it is very time-consuming to put the qualified triples into the vector and then deduplicate them, and it is easy to time out.

The time complexity can be O(n^2), but it is still time-consuming because it is not easy to do pruning operations .

double pointer method

The double pointer method is more efficient than the hash method. Let’s look at the following animation:
insert image description here
first sort the array, and then have a layer of for loop, i starts from the subscript 0, and at the same time define a subscript left at the position of i+1, define The subscript right is at the end of the array.

Still find abc in the array so that a + b +c = 0, here we are equivalent to a = nums[i], b = nums[left], c = nums[right].

Move left and right:

  • If nums[i] + nums[left] + nums[right] > 0, it means that the sum of the three numbers is larger at this time, because the array is sorted, so the right subscript should move to the left, so that the three numbers The sum is smaller.
  • If nums[i] + nums[left] + nums[right] < 0, it means that the sum of the three numbers is smaller at this time, and left moves to the right to make the sum of the three numbers larger.

Until left meets right.

Difficulties Encountered During Implementation

Not very familiar with deduplication operations

deduplication logical thinking

In fact, the main consideration is the deduplication of three numbers. a, b, c, corresponding to nums[i], nums[left], nums[right]

deduplication of a

What if a is repeated, a is the element traversed in nums, so it should be skipped directly.

But is it to judge whether nums[i] is the same as nums[i + 1], or whether nums[i] is the same as nums[i-1]? All are compared with nums[i], is it compared to its previous one, or its latter one?

If we compare its latter one:

if (nums[i] == nums[i + 1]) {
    
     // 去重操作
    continue;
}

Then we pass the case of repeated elements in the triplet directly. For example, {-1, -1 ,2} This set of data, when traversing to the first -1, it is judged that the next one is also -1, then this set of data is passed.

But remember that we cannot have repeated triples, but the elements within triples can be repeated!

At this point there are two repeating dimensions.

So should compare its previous one:

if (i > 0 && nums[i] == nums[i - 1]) {
    
    
    continue;
}

To write this way is currently using nums[i], we judge whether the previous one is the same element, looking at the set of data {-1, -1 ,2}, when traversing to the first -1, as long as the previous one If there is no -1, then {-1, -1 ,2} can also be included in the result set.

Deduplication of b and c

When deduplication logic is added

the code

class Solution {
    
    
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
    
    
        unordered_set<int> result_set;
        unordered_set<int> nums_set(nums1.begin(),nums1.end());
        for(int num : nums2){
    
    
            if(nums_set.find(num) != nums_set.end()){
    
    
                result_set.insert(num);
            }
        }
        return vector<int>(result_set.begin(),result_set.end());
    }
};

Question 202. Happy Numbers

See the title first thought

Title description:

Write an algorithm to determine whether a number n is a happy number.

"Happy number" is defined as: For a positive integer, replace the number with the sum of the squares of the numbers in each position each time, and then repeat this process until the number becomes 1, or it may be an infinite loop but it will never change to 1. If it can become 1, then this number is a happy number.

Return True if n is a happy number; False if not.

Have the following ideas:

Key: ** If the loop is infinite, the sum will appear repeatedly during the summing process**

Therefore, the hash method is used to judge whether the sum is repeated. If it is repeated, it returns false , otherwise, the sum is found until it is 1.

You can use unordered_set to determine whether the sum is repeated .

Thoughts after reading the code caprice

same idea

Difficulties Encountered During Implementation

I am not very familiar with the singular operation on each digit of the value

the code

class Solution {
    
    
public:
    // 取数值各个位上的单数之和
    int getSum(int n) {
    
    
        int sum = 0;
        while (n) {
    
    
            sum += (n % 10) * (n % 10);
            n /= 10;
        }
        return sum;
    }
    bool isHappy(int n) {
    
    
        unordered_set<int> set;
        while(1) {
    
    
            int sum = getSum(n);
            if (sum == 1) {
    
    
                return true;
            }
            // 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false
            if (set.find(sum) != set.end()) {
    
    
                return false;
            } else {
    
    
                set.insert(sum);
            }
            n = sum;
        }
    }
};

1. The sum of two numbers

See the title first thought

Title description:

Given an integer array nums and a target value target, please find the two integers whose sum is the target value in the array, and return their array subscripts.

It is difficult to solve this problem, and I don't know much about map.

Thoughts after reading the code caprice

This question needs a collection to store the elements we have traversed, and then ask this collection when traversing the array, whether an element has been traversed, that is, whether it appears in this collection.

In this question, we not only need to know whether the element has been traversed, but also know the subscript corresponding to this element . We need to use the key value structure to store, the key to store the element , and the value to store the subscript , so it is appropriate to use map .

Why use the set used before?

  • The size of the array is limited, and if there are few elements and the hash value is too large, memory space will be wasted.
  • set is a collection, and the element in it can only be a key . For the question of the sum of two numbers, it is not only necessary to judge whether y exists, but also to record the subscript position of y, because the subscripts of x and y must be returned. So set can't be used either.

The map is a key value storage structure, you can use the key to save the value, and use the value to save the subscript where the value is located.

Among the three types of map in C++, choose std::unordered_map , because the order of keys is not required in this question, and it is more efficient to choose std::unordered_map .

When using map, pay attention to the following two points:

  • what is map used for
  • What do the key and value in the map represent?

Regarding the first point, the purpose of map is to store the elements we have visited, because when traversing the array, we need to record which elements we have traversed before and the corresponding subscripts, so that we can find the one that matches the current element (that is, add equal to target)

Regarding the second point, for this question, we need to give an element, determine whether this element has appeared, and if so, return the subscript of this element.

To judge whether an element appears, this element will be used as a key, so the element in the array is used as a key, and the key corresponds to the value, and the value is used to store the subscript.

So the storage structure in the map is {key: data element, value: subscript corresponding to the array element}.

When traversing the array, you only need to query the map to see if there is a value that matches the currently traversed element . If so, it is the found matching pair. If not, put the currently traversed element into the map, because the map stores is the element we visited.

The implementation process is as follows:
insert image description here

Difficulties Encountered During Implementation

I am not very familiar with the singular operation on each digit of the value

the code


Harvest today

1. Have an understanding of the basic theory of the hash table

2. Know the application scenarios of set and map

3. I am still not very proficient in using the template library, and I need to strengthen it in the future

Today's study time is 3 hours

The pictures in this article are all from Carl’s code caprice, and I would like to thank you very much

Guess you like

Origin blog.csdn.net/m0_46555669/article/details/127079009