242.有效的字母异位词
暴力解法:在暴力法这里花费了很久,因为两个for循环的i++、j++都需要自己定义,不是单纯的每个循环都加加,因为使用了erase擦除操作,会改变size。
排序法: 字符串的字母是有ASCII值的 是可以用sort来进行排序的
class Solution {
public:
bool isAnagram(string s, string t) {
sort(s.begin(),s.end());//因为字符串也可以根据ASCII直接来排列大小
sort(t.begin(),t.end());
return s==t?true:false;//三目运算符
}
};
哈希表 数组方法
class Solution {
public:
bool isAnagram(string s, string t) {
int hash[26]={0};//创建26个0的数组,构建hash table,因为是小写字母,只有26个,如果有多个相同的就是哈希碰撞
for(int i=0;i<s.size();i++){
//我们知道小写字母的ASCII值是连续的,那么a对应0的位置的话,z就会对应第26-1 25的位置
//并不需要记住字符a的ASCII,只要求出一个相对数值就可以了 这样得到字母在hash中相对位置
hash[s[i]-'a']++;//s1[i]-'a'是为了将a变成0,b变成1,c变成2... 而整个的意思是相关字母在s中出现了,就在对应的哈希表的位置上++,比如a就在a的位置上 原来的数字+1...他是会自己识别的,注意这里的哈希表值得是我构建的hash数组
}
for(int j=0;j<t.size();j++){
hash[t[j]-'a']--;//根据t[j] 对应的对哈希表上的数字进行--处理
}
for(int u=0;u<26;u++){
if(hash[u]!=0){
// hash数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
return false;
}
}
// hash数组所有元素都为零0,说明字符串s和t是字母异位词
return true;
}
};
349. 两个数组的交集
哈希表 set 方法
先把num1 进行unordered操作,记录到一个 unordered_set里面,然后用num2进行find,如果find出来,再把其放到空的unordered_set里面
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> result_set;//unordered_set 可以直接帮我们进行去重操作,比如有100个2 unordered_set之后就只剩1个2 之所以用set是为了给结果集去重 创建了一个新的result_set 作为接受结果的数组
unordered_set<int> nums_set(nums1.begin(),nums1.end());//用set操作对nums1进行去重 存放 这里只能是用这种写法,用拷贝构造会出错
for(int num:nums2){//这里的:意思是迭代,即不断从nums2里取其中的元素,赋值给临时变量num
if(nums_set.find(num)!=nums_set.end()){//set::find是C++ STL中的内置函数,该函数将迭代器返回到在集合容器中搜索的元素。如果找不到该元素,则迭代器将指向集合中最后一个元素之后的位置 所以这里的if满足的话 就是在nums_set中找到了num
result_set.insert(num);//把num插入到result_set这个哈希表里
}
}
return vector<int> (result_set.begin(),result_set.end());//vector 的赋值只能这样写 带begin end这种
}
};
哈希表 数组方法
这道题LeetCode上面给限制了数的大小,所以也可以用哈希表的数组来做,只是空间占用多了一点
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> result_set; // 存放结果,之所以用set是为了给结果集去重
int hash[1005] = {0}; // 默认数值为0 这里1005也可以是1003... 只要是比1000多就行
for (int num : nums1) { // nums1中出现的字母在hash数组中做记录
hash[num] = 1;
}
for (int num : nums2) { // nums2中出现话,result记录
if (hash[num] == 1) {
result_set.insert(num);//记录相等的数
}
}
return vector<int>(result_set.begin(), result_set.end());
}
};
202. 快乐数
哈希表 set方法
题目中说到会无限循环,那么如果无限循环,就是sum会重复出现。遇到需要快速判断元素是否在集合出现的时候,就可以考虑哈希表
class Solution {
public:
int getHappy(int n){//自己构造一个函数以便每次求数字的平方和
int sum=0;
while(n){//n=0时退出while循环 这里对正整数每个位置上的数字进行平方和
sum+=(n%10)*(n%10);//%是取余 注意这里在运算时候需要加上(),不然运算顺序会出错
n=n/10;
}
return sum;
}
bool isHappy(int n) {
unordered_set<int> set;//创建一个空的名为set的容器 哈希表
while(1){
int sum=getHappy(n); //调用函数
if(sum==1){
return true;
}
if(set.find(sum)!=set.end()){
return false;//如果有相等的 那么一定是陷入了无限循环
}else{
set.insert(sum);//找不到 就把num传入到set里面 先记录着
}
n=sum;//让n=sum,让其进入下个循环
}
}
};
1. 两数之和
暴力解法
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for(int i=0;i<nums.size();i++){
for(int j=i+1;j<nums.size();j++){
if(nums[i]+nums[j]==target){
return {i,j};//这里一开始写的vector<int> {i,j}这样是错误的 因为vector容器不能这样赋值 不好用vector容器 一般暴力解法好像不怎么涉及到其他容器,哈希表解法倒是经常用
}
}
}
return {};
}
};
哈希表 map解法
map 首先一点重要的就是有key value 两个存储结构,而key是用来判断元素是否出现过的,那么结合题意,key就是数组中的数,value就是对应的下标
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
//首先创建一个unordered_map 哈希表 起名map 因为数组位置和数组元素都是int型 所以map也需要对应
unordered_map<int,int> map;
//开始遍历
for(int i=0;i<nums.size();i++){
//map记录的是遍历过得数据 而map中的key指的是用来判断元素是否出现,这里数组元素就是key,那么数组下标就是value
auto iter=map.find(target-nums[i]);//用来找当处于i的时候,map中有没有与num[i]相加得到target的key
if(iter!=map.end()){//iter不等于map.end的意思是在map中找到了key
return {iter->second,i};//这里iter->first 指的是key, iter->second 指的是value
}
else{//如果map中没有,那么就这个把nums[i],i存在map中
map.insert({nums[i],i});//map 的顺序是key,value
//map.insert(pair<int,int>(nums[i],i));代码随想录中是这样写的
}
}
return {};//没有的话就return出一个空
}
};