链接:力扣1
描述:
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
思路:数组其实就是一个简单哈希表,而且这道题目中字符串只有小写字符,那么就可以定义一个数组,来记录字符串s里字符出现的次数。
字符a到字符z的ASCII是26个连续的数值,所以字符a映射为下标0,相应的字符z映射为下标25。
再遍历 字符串s的时候,只需要将 s[i] - ‘a’ 所在的元素做+1 操作即可,并不需要记住字符a的ASCII,只要求出一个相对数值就可以了。
统计完s中的字符以后,如何判断t中的字符呢?只需要同样遍历一遍,对hashtable中相应的索引减一,最后看hashtable中是否全为0,只要有一个非零,那么就返回false,全为0,则返回true
代码如下:
#include
using namespace std;
class Solution
{
public:
bool isAnagram(string s, string t)
{
int hashtable[26] = { 0 };
for (int i = 0; i < s.size(); i++)
{
hashtable[s[i] - 'a']++;
}
for (int j = 0; j < t.size(); j++)
{
hashtable[t[j] - 'a']--;
}
//思考了很久,如果一旦有一个不为0,则说明有字母不一样
for (int i = 0; i < 26; i++)
{
if (hashtable[i])
return false;
}
return true;
}
};
int main()
{
string s = "anagram";
string t = "nagaram";
Solution q;
cout<
运行结果:
链接:力扣2
描述:给定两个数组 nums1
和 nums2
,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
思路:
1、暴力求解。两个for循环,因为最后的结果中的交集是无重复的,所以用一个set容器来存放结果。最后可直接用set的迭代器返回一个vector容器。
2、用unordered_set容器做hashtable,因为最后的结果中的交集是无重复的,所以用一个unordered_set容器来存放结果。同时将其中一个容器nums1转为哈希表,遍历另外一个容器,利用set的查找功能,如果在hashtable中,就存在结果容器里。
for (int num : nums2)的写法值得注意,数组也可以这么干。
#include
#include
#include
using namespace std;
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)
{
//发现nums2的元素,在nums_set的出现过
if (nums_set.find(num) != nums_set.end())
{
result_set.insert(num);
}
}
return vector(result_set.begin(), result_set.end());
}
};
int main()
{
Solution s;
vectorv1{ 2,4,7,5,5 };
vectorv2{ 2,5,5 };
vectorret= s.intersection(v1, v2);
return 0;
}
结果如下:
链接:力扣3
描述:
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
思路:
既然需要求每个位置上的和,那么可以先写一个成员函数求各个位置的和。题目告诉了可能出现无限循环,那么如果某次的和等于之前求出来的和了,说明陷入了无限循环,即不是快乐数。因此需要记录之前的和,所以要用unordered_set记录出现的sum。先判断第一次的sum是否为1,是1就返回true,如果某次查找到了sum在set里,则返回false,接着加入set里。
代码如下:
#include
#include
using namespace std;
class Solution {
public:
int Getsum(int n)
{
int sum = 0;
//求每个位置上的数字平方和
while (n)
{
sum += pow((n % 10), 2);
n /= 10;
}
return sum;
}
bool isHappy(int n)
{
unordered_sets;
while (1)
{
int sum = this->Getsum(n);
if (sum == 1)
return true;
if (s.find(sum) != s.end())
{
//如果在unordered_set中找到了重复值,说明陷入循环了
//就不是快乐数了
return false;
}
s.insert(sum);
n = sum;
}
}
};
int main()
{
Solution s;
cout<
运行结果:
链接:力扣4
描述:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
思路:
四点内容:
1、什么时候使用哈希法?当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法。
本题呢,我就需要一个集合来存放我们遍历过的元素,然后在遍历数组的时候去查询这个集合,需要查找的元素是target-nums[i],是否出现在这个集合。如果存在,则返回查找到的下标和当前遍历的下标。
2、用哪种哈希结构?
这道题目中并不需要key有序,选择std::unordered_map 效率更高!只能用unordered_map,不仅可以存元素,还可以存元素下标。需要用key存元素,value存下标。
3、map里存的什么数?
存的之前遍历过的数组元素以及下标。每次都需要在map里查找,查找成功就返回,否则就加入。
代码如下:
#include
#include
#include
using namespace std;
class Solution {
public:
vector twoSum(vector& nums, int target)
{
unordered_mapm;
for (int i = 0; i < nums.size(); i++)
{
int s = target - nums[i];
unordered_map::iterator mit = m.find(s);
if (mit != m.end())
{
//找到了该值
return vector{(*mit).second,i};
}
else
m.insert(make_pair(nums[i], i));
}
return vector{};
}
};
int main()
{
Solution s;
vectorv{ 2, 7, 11, 15 };
vectorret = s.twoSum(v, 9);
return 0;
}
结果如下: