序文
Little KのLeetcodeへようこそ|Code Random Thoughts |専門コラム、今日はハッシュをお届けします~Happy Numbers|4 つの数字の足し算 II|身代金の手紙の共有✨
202. ハッピーナンバー
✨タイトルリンクここをクリックして、
数値 n が幸せな数値であるかどうかを判断するアルゴリズムを作成します。
「ハッピーナンバー」は次のように定義されます。
- 正の整数の場合、数値は各位置の数字の二乗の合計で置き換えられます。
- 次に、数値が 1 になるまでこのプロセスを繰り返します。または、無限ループになる可能性がありますが、数値が 1 より小さくなることはありません。
- この処理の結果が 1 であれば、その数値は幸せな数値です。
n が適切な数の場合は true を返し、それ以外の場合は false を返します。
例 1:
入力: n = 19
出力: true
説明:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
例 2:
入力: n = 2
出力: false
ヒント:
1 <= n
<= 231 - 1
アイデア: 「幸せな数」の 2 番目の定義 - 次に、その数が 1 になるまでこのプロセスを繰り返します。または、無限ループになる可能性がありますが、決して 1 に変化しません。つまり、これが繰り返されるとき、その数は間違いなく幸せな数ではありません。しかし、数値がセットに含まれているかどうかをすばやく判断したい場合は、当然ハッシュを考えることになります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. 4 つの数の足し算 II
✨タイトルリンク ここをクリックする
と、4 つの整数配列 nums1、nums2、nums3、nums4 が与えられます。配列の長さは n です。満たすタプル (i、j、k、l) の数を計算してください。0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
例 1:
入力: nums1 = [1,2]、nums2 = [-2,-1]、nums3 = [-1,2]、nums4 = [0,2]
出力: 2
説明:
2 つのタプルは次のとおりです。
- (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
例 2:
入力:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]
出力: 1
ヒント:
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
「アイデアは次のとおりです。」
まず unowned_map を定義し、キーには a と b の合計を、値には a と b の合計の出現回数を入れます。
big A 配列と big B 配列を走査し、2 つの配列の要素の合計と出現回数を数え、それらをマップに入れます。
a+b+c+d = 0 の出現回数をカウントする int 変数 count を定義します。
big C 配列と big D 配列を走査した後、マップ内に 0-(c+d) が出現した場合は、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. 身代金の手紙
✨タイトルリンクをクリックすると、と
という2つの文字列が表示され、中の文字で構成できるかどうかを判断します。はいの場合は戻り、そうでない場合は戻ります。の各文字は で1 回だけ使用できます。ransomNote
magazine
ransomNote
magazine
true
false
magazine
ransomNote
例 1:
入力: ransomNote = "a"、magazine = "b"
出力: false
例 2:
入力: ransomNote = "aa"、magazine = "ab"
出力: false
例 3:
入力: ransomNote = "aa"、magazine = "aab"
出力: true
ヒント:
1 <= ransomNote.length, magazine.length
<= 105
ransomNote
で、magazine
英小文字で構成されます
「方法 1」: 暴力的な方法、直接 2 層for
ループ、マガジン内に ransomNote の要素がある場合、ransomNote から削除し、最後に ransomNote のサイズがゼロかどうかを確認します。
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;
}
};
「方法 2」: ハッシュ法。私の最初のアイデアは、マップを使用することです。マップのアイデアは、文字をキーとして使用し、値を使用して出現回数を記録します。最初に ransomNote をマップに配置し、次にマップを使用して雑誌内の要素を検索し、1 を見つけて 1 を減算し、最後にマップ内の値が 0 以下であるかどうかを確認します。
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;
}
};
「方法 3」: マップは赤黒ツリーまたはハッシュ テーブルを維持する必要があり、ハッシュ関数も実行する必要があるため、時間がかかります。したがって、ここで配列をハッシュ テーブルとして使用すると、マップよりも高速になります。!!
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;
}
};
要約する
ハッシュテーブルには配列、、、の3つの構造がありset
、map
状況に応じて適切に選択する必要があります~