题目链接:有效的字母异位词
文章链接:有效的字母异位词
视频链接:有效的字母异位词
因为C++还在学习中,没有到set和map这里,只能先看视频讲解了。但多多少少还有点思路,能否实现不清楚,思路是这样的:创建虚拟数组,遍历第一个字符串,记录每个元素出现的次数,放入虚拟数组中;同样创建另一个虚拟数组,遍历第二个字符串,记录每个元素出现的次数,放入该虚拟数组中。之后,同时遍历这两个虚拟数组,观察是否每个元素出现的次数相同即可。
----------------------------------------以下是看完视频总结的思路-------------------------------------
思路和卡哥大致相同,卡哥的思路:这道题字符串的元素都是a~z,ASCII码都是连续,所以创建一个长度为26的哈希数组就够了,下标0代表a的出现次数,下标1代表b的出现次数,以此类推。然后开始遍历第一个字符串,记录每个字母出现的次数,再遍历第二个字符串,记录每个字母出现的次数,二者相减,每个元素出现次数的差值都为0,则这两个字符串互为字母异位词。
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;
}
};
题目链接:两个数组的交集
文章链接:两个数组的交集
视频链接:两个数组的交集
第一反应是用哈希数组,大致思路和242.有效的字母异位词相同,定义两个哈希数组,遍历数组num1,将每个数字出现的次数依次记录在哈希数组中,如哈希数组下标为0对应的值指的是数组num1中0出现的次数,然后再遍历数组num2,将每个数字出现的次数依次记录在另一个哈希数组中。之后,遍历两个虚拟数组,如果相同下标对应的元素的值都不为0就是它们交集中的元素,保存到另一个数组中即可。
但是,卡哥在242.有效的字母异位词视频讲解里提到,三种哈希结构:数组、set、map。当数据量比较少,且范围也比较小时尽量用数组,数据量比较大的时候用set,要用key-value的时候用map。因为这道题中提示数组的元素范围是[1,1000],所以我估摸着用数组的话内存开销可能会很大,但set我还没学到…只能先用数组了。
----------------------------------------以下是看完视频总结的思路-------------------------------------
果不其然,卡哥还是比较倾向用set作为哈希表的。思路:将数组nums1进行处理转为哈希表,然后查询数组nums2里的元素是否在哈希表里出现过,出现就存入result集合里,这里的result集合是去重的,最终返回result集合即可。
class Solution {
public:
vector intersection(vector& nums1, vector& nums2) {
unordered_set result_set;
int hash[1005] = {0};
for(int i = 0;i < nums1.size(); i++)
{
hash[nums1[i]] = 1;
}
for(int j = 0;j < nums2.size();j++)
{
if(hash[nums2[j]] == 1)
result_set.insert(nums2[j]);
}
return vector(result_set.begin(), result_set.end());
}
};
//set实现
class Solution {
public:
vector intersection(vector& nums1, vector& nums2) {
unordered_set result_set; //
unordered_set nums_set(nums1.begin(), nums1.end());
for (int num : nums2) {
if (nums_set.find(num) != nums_set.end()) {
result_set.insert(num);
}
}
return vector(result_set.begin(), result_set.end());
}
};
题目链接:快乐数
文章链接:快乐数
因为对取数值各个位上的单数操作不熟悉,所以我直接看了卡哥的代码。
----------------------------------------以下是看完文章总结的思路-------------------------------------
如果一个数是快乐数,那说明它每位上的数的平方和一定是不同的,如果有一个和重复出现就说明它不是快乐数。因为当我们遇到了要快速判断一个元素是否出现在集合里的时候就要考虑哈希法了,而且这题涉及到去重,所以可以使用unordered_set。
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 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;
}
}
};
题目链接:两数之和
文章链接:两数之和
视频链接:两数之和
一时暴力一时爽,一直暴力一直爽。直接两层for循环枚举所有情况即可。不过时间开销很大,所以我选择看下卡哥的视频讲解。详细思路可以看上方的文章链接,注意map的作用。
class Solution {
public:
vector twoSum(vector& nums, int target) {
std::unordered_map map;
for(int i = 0; i < nums.size(); i++) {
// 遍历当前元素,并在map中寻找是否有匹配的key
auto iter = map.find(target - nums[i]);
if(iter != map.end()) {
return {iter->second, i};
}
// 如果没找到匹配对,就把访问过的元素和下标加入到map中
map.insert(pair(nums[i], i));
}
return {};
}
};