目录
242.有效的字母异位词
题目链接
(1)文字讲解:https://programmercarl.com/0242.有效的字母异位词.html#思路
(2)视频讲解:
(3)题目链接:https://leetcode.cn/problems/valid-anagram/description/
看到题解之前的想法
用一个数组存字母以及出现的次数,两个句子得到两个数组,比较他们每一个元素(数组)的数量是否相同。
看到题解之后的想法
不需要两个数组计数,只需要在A字符串的时候++,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;
}
};
349. 两个数组的交集
题目链接
(1)文字讲解:https://programmercarl.com/0349.两个数组的交集.html#算法公开课
(2)视频讲解:
(3)题目链接:https://leetcode.cn/problems/intersection-of-two-arrays/
看到题解之前的想法
不会写,完全不知道set的相关函数,而且这个题目的元素不像上一个题目一样是有限的,不可以用数组存放。
看到题解之后的想法
1.使用unordered_set存储nums1
2.对于nums2中的每一个元素,查询是否在这个set中,如果在,存到result_set中(因为nums2中的元素可能有重复,所以存放结果的也需要是set)
3.result_set转成vector
本题难点
unordered_set的基本操作
代码
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());
}
};
202. 快乐数
题目链接
(1)文字讲解:https://programmercarl.com/0202.快乐数.html#思路
(2)视频讲解:
(3)题目链接:https://leetcode.cn/problems/happy-number/
看到题解之前的想法
不知道怎么做
看到题解之后的想法
1.题目有提示,只有两种情况,无限循环和1。如果是无限循环,那么说明结果是重复出现的;也就是说,一旦重复出现,说明就不会返回1了
2.检查某个元素是否出现在某个集合中一定要想到用哈希表
3.思路很清晰了,将结果都存在orderset中,如果发现了有重复的,那就return false,否则return true。
本题难点
1.题意理解,只有重复出现和1两种情况
2.灵活运用哈希表
代码
class Solution {
public:
int getSquare(int num){
int tmp = num;
int sum = 0;
int res = 0;
while(tmp){
res = tmp%10;
tmp = tmp/10;
sum += res*res;
}
return sum;
}
bool isHappy(int n) {
unordered_set<int> res_set;
while(n!=1){
n = getSquare(n);
if(res_set.find(n) == res_set.end()){
res_set.insert(n);
}else{
return false;
}
}
return true;
}
};
1. 两数之和
题目链接
(1)文字讲解:https://programmercarl.com/0001.两数之和.html#算法公开课
(2)视频讲解:
(3)题目链接:https://leetcode.cn/problems/two-sum/description/
看到题解之前的想法
经过上面几题的历练,我想的是,用一个unordered_set先存储整个数组,然后遍历,如果target减去遍历到的元素得到的值能在set里面找到,那么记录这个元素的下标,退出循环,再次遍历数组,寻找到target-nums[i]这个数的下标(因为set只能提供找没找到,下标是不知道的),代码如下:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_set<int> nums_set(nums.begin(), nums.end());
int i = 0, j = 0;
for(; i< nums.size(); i++){
if(nums_set.find(target-nums[i]) != nums_set.end())
{
break;
}
}
int target_num = target-nums[i];
for(int j = 0; j < nums.size(); j++){
if(nums[j] == target_num){
break;
}
}
return vector<int>{i, j};
}
};
但是这样是有问题的,如果遇到这样的示例:
也就是数组中有元素的两倍就等于target,那么在遍历到这个元素的时候,就算这个元素只出现了一遍,他就会返回这个函数的下标两次作为答案。因为,我先在set中将整个数组预存进去了,所以才会分不清楚元素出现了几次。
看到题解之后的想法
1.set不能存储下标,unordered_map更为合适,key是数据元素值,value是元素下标,这样可以根据key来寻找是否有需要的值,返回value
2.不是先把所有的数组元素预存在map中,而是,遍历数组,如果在当前的map中能找到当前元素的“互补”,那么返回找到的下标;否则将这个元素加到map中。这样就避免了上面我碰到的问题,就算是某个元素的两倍就等于target,也必须要第二次碰到这个元素才能成功。
3.按照这个思路,其实set也行,不是非要用map,就是要再遍历一遍数组找出来那个值。(不用担心当元素重复时,返回和上一轮遍历中相同的下标,因为上一轮找到的一定是第二个这个重复元素,我们按照顺序再次遍历只会找到第一个这个元素)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_set<int> nums_set;
int i = 0, j = 0;
for(; i< nums.size(); i++){
if(nums_set.find(target-nums[i]) != nums_set.end())
{
break;
}else{
nums_set.insert(nums[i]);
}
}
int target_num = target-nums[i];
for(; j < nums.size(); j++){
if(nums[j] == target_num){
break;
}
}
return vector<int>{i, j};
}
};
本题难点
1.想到使用map
2.不是预存所有元素值,而是先遍历,以避免一个元素的两倍恰好是target的情况。
代码
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
std::unordered_map<int, int> map;
for(int i = 0; i <nums.size(); i++){
auto iter = map.find(target-nums[i]);
if (iter != map.end()){
return {iter->second, i};
}else{
map.insert(pair<int, int>(nums[i], i));
}
}
return {};
}
};