foreword
Welcome to Little K 's Leetcode|Code Random Thoughts | Specialized column, today I will bring you hashing~Happy Numbers|Addition of Four Numbers II|Sharing of Ransom Letter✨
Table of contents
202. Happy Numbers
✨Title linkClick here
to write an algorithm to judge whether a number n is a happy number.
"Happy Number" is defined as:
- For a positive integer, each time the number is replaced by the sum of the squares of the digits in each position.
- Then repeat this process until the number becomes 1, or it may be an infinite loop but it never becomes less than 1.
- If the result of this process is 1, then the number is a happy number.
Returns true if n is a happy number; otherwise, returns false.
Example 1:
Input : n = 19
Output : true
Explanation :
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
Example 2:
Input : n = 2
Output : false
hint:
1 <= n
<= 231 - 1
Idea: The second definition of "happy number" - then repeat this process until the number becomes 1, or it may be an infinite loop but it will never change to 1, that is to say, when it repeats, the number is definitely not a happy number~ But when we want to quickly judge whether a number appears in the set, we naturally think of hashing sum
!
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;
}
if (set.find(sum) != set.end()) {
return false;
}
else set.insert(sum);
n = sum;
}
}
};
454. Adding Four Numbers II
✨Title Link Click here
to give you four integer arrays nums1, nums2, nums3 and nums4, the length of the array 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
Example 1:
Input : nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
Output : 2
Explanation :
The two tuples are as follows:
- (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
- (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0
Example 2:
input : nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]
output : 1
hint:
n == nums1.length
n == nums2.length
n == nums3.length
n == nums4.length
1 <= n <= 200
-228 <= nums1[i], nums2[i], nums3[i], nums4[i] <= 228
"The idea is as follows":
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.
Traverse the big A and big B arrays, count the sum of the elements of the two arrays, and the number of occurrences, and put them in the map.
Define the int variable count to count the number of occurrences of a+b+c+d = 0.
After traversing the big C and big D arrays, 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.
Finally, return the statistical value count
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
//key存放nums1和nums2中值的和,value则记录该值出现的次数
unordered_map<int,int> umap;
//遍历nums1和nums2数值,记录他们的和出现的次数,并放入map中
for (auto a : nums1) {
for (auto b : nums2) {
umap[a+b]++;
}
}
int count = 0; //记录四数之和等于零
//遍历nums3和nums4数组,如果他们的和等于map中任意一值的相反数,则用count记录该和出现的次数
//也就是四数之和等于零的次数
for (auto c : nums3) {
for (auto d : nums4) {
if (umap.find(- (c + d)) != umap.end()) {
count += umap[- (c + d)];
}
}
}
return count;
}
};
383. Ransom letter
✨The title link click here
to give you two strings: ransomNote
and magazine
, to judge ransomNote
whether it can be magazine
composed of characters inside. Return if yes true
; otherwise return false
. magazine
Each character in can only ransomNote
be used once in .
Example 1:
Input : ransomNote = "a", magazine = "b"
Output : false
Example 2:
Input : ransomNote = "aa", magazine = "ab"
Output : false
Example 3:
Input : ransomNote = "aa", magazine = "aab"
Output : true
hint:
1 <= ransomNote.length, magazine.length
<= 105
ransomNote
and magazine
consists of lowercase English letters
"Method 1": Violent method, direct two-layer for
loop, if there is an element of ransomNote in the magazine, then delete it from ransomNote, and finally check whether the size of ransomNote is zero
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
for (int i = 0; i < magazine.size(); i++) {
for (int j = 0; j < ransomNote.size(); j++) {
if (magazine[i] == ransomNote[j]) {
ransomNote.erase(ransomNote.begin() + j);
break;
}
}
}
if (ransomNote.size() == 0) return true;
return false;
}
};
"Method 2": Hash method, my first idea is to use map, map idea, use letters as keys, use value to record the number of occurrences, first put ransomNote into the map, then use the map to find elements in the magazine, find one and subtract one, and finally check whether the values in the map are less than or equal to zero.
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
if (magazine.size() < ransomNote.size()) return false;
unordered_map<char,int> umap;
for (int i = 0; i < ransomNote.size() ; i++) umap[ransomNote[i]]++;
for (int i = 0; i < magazine.size(); i++) umap[magazine[i]]--;
for (int i = 0; i < ransomNote.size() ; i++) {
if (umap[ransomNote[i]] > 0)
return false;
}
return true;
}
};
"Method 3": Because the map needs to maintain a red-black tree or a hash table, and also needs to do a hash function, it is time-consuming! So using an array as a hash table here is faster than a map! ! !
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
if (ransomNote.size() > magazine.size()) return false;
int record[26] = {
0};
for (int i = 0; i < ransomNote.size(); i++) record[ransomNote[i] - 'a']++;
for (int i = 0; i < magazine.size(); i++) record[magazine[i] - 'a']--;
for (int i = 0; i < 26; i++) {
if (record[i] > 0) {
return false;
}
}
return true;
}
};
Summarize
Hash tables have three structures, arrays, set
, map
, and should be selected appropriately according to the situation~