242 有效的字母异位词
题目链接:有效的字母异位词
题目描述:给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
解题思想:根据题目给出的注意,很容易知道,我们只需要比对s和t中的每次字符出现的次数,如果出现的字符及其相关的次数相同,就返回为true。
因此,解题方法为:只需要将s中的每个字母出现的次数存入哈希表dict中,再遍历t中的字母,将dict中的次数减去,若最后每个字母的出现次数等于0,即表明最后是字母异位词。
法一:
class Solution {
public:
bool isAnagram(string s, string t) {
unordered_map<char,int>dict;
for(char c:s)
{
dict[c]++;
}
for(char c:t)
{
dict[c]--;
}
for(auto iter=dict.begin();iter!=dict.end();iter++)
{
if(iter->second!=0)
return false;
}
return true;
}
};
这里采用的是哈希表。
注意哈希表的使用方法:
1.哈希表的构造:
unordered_map<int,int>dict;
2.哈希表的插入:
dict.emplace(1,2);
dict.insert(pair<int,int>(1,2));
dict[1]=2;
- 哈希表的遍历:
for(auto iter=dict.begin();iter!=dict.end();iter++)
{
cout<<iter->first<<iter->second;
}
以上是哈希表的简单使用方法。
在本题中,可以简单的使用数组代替哈希表。(换句话说,数组就其实是哈希表,哈希表的key值其实就是数组中的索引下标i,哈希表中的value就是数组的值)
法二:使用数组代替哈希表
class Solution {
public:
bool isAnagram(string s, string t) {
int dict[26]={0};//作为字典,存的是s
for(char c: s)
{
dict[c-'a']++;//将s每个字母存入dict里面
}
for(char c:t)
{
dict[c-'a']--;
}
for(int i=0;i<26;i++)
{
if(dict[i]!=0)
return false;
}
return true;
}
};
349、两个数组的交集
题目链接:两个数组的交集
题目描述:给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
解题思路:返回两个交集,直观的想法,我们只需要将第一个数组去重后的结果存放,第二个数组也进行相关去重后与之进行比对即可。
由于此题,我们不需要记住数组中的数字出现的次数。因此,我们采用set即可。
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
vector<int>result;
if(nums1.size()==0&&nums2.size()==0) return result;
unordered_set<int>set1;//存入nums1
for(int i:nums1)
{
set1.emplace(i);//将num1中的每个字母都存入set1中,同时由于set是不允许遍历的,也可以去除重复的值。
}
for(int i:nums2)
{
if(set1.count(i))
{
result.push_back(i);
set1.erase(i);//将i从set中删除,也可以去除重复的值。
}
}
return result;
}
};
此代码存在的问题还是set的使用不多,使用出现了较为复杂的做法,因此,可以进行相关的改进。
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int>result;
unordered_set<int>set1(nums1.begin(),nums1.end());
for(int num:nums2)
{
if(set1.find(num)!=set1.end())
result.insert(num);
}
return vector<int>(result.begin(),result.end());
}
};
202.快乐数
题目链接:快乐数
题目描述:
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
题目解法:
该题同样采用的是哈希表中set的用法。
需要注意的1. 需要学会如何计算每个位置上的数字的平方和。即需要弄清楚取余%和取整 / 两个符号的用法。
2. 需要注意的是如何跳出这个循环,在本题中,如果得到的平方和,在set中已经存在过了,说明该数字必定不是快乐数,将会永远陷入无限循环中。得到了这个结论,那整体的算法便很容易知道,即,只需要将每次得到的平方和存入set中,并判断是否为1,是1则将跳出循环,若存在,则返回false,跳出,若不存在,将其加入set即可。
class Solution {
public:
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;
}
return false;
}
int getSum(int n)
{
int sum=0;
while(n)
{
sum+=(n%10)*(n%10);
n=n/10;
}
return sum;
}
};
1. 两数之和
题目链接:噩梦开始的地方
题目描述:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
解题思想:
- 暴力解法,是否循环遍历,将其每两个数字的和存入map中,并且存入相关的下标值。
- 采用map的方法,循环一次即可。通过遍历数组,找map中找到target-nums[i]值,如果找到,则表明在map中该数字已经遍历过了,我们只需要返回该下标和已经存在map中的下标即可。
注意事项:我们需要十分熟悉,在该题中,map是用来干啥的。
map是用来存放已经遍历过的数字及其下标的,当我们遍历新的数字是,我们便需要知道是否已经遍历过了target与该数字的差的值。因此,map便于这个用途。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
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};//表示已经找到了,返回相应的值,其中iter->second表示已经找到的值的下标,而i表示当前的下标
}
else{
map.insert(pair<int,int>(nums[i],i));//未找到,将该数字及其下标存入map中。
}
}
return {};
}
};