@代码随想录算法训练营第6天(第5天周日休息) | LeetCode454 四数相加||,383 赎金信,15 三数之和,18 四数之和
题目链接: https://leetcode.cn/problems/valid-anagram/description/
视频链接:
https://programmercarl.com/0024.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9.html
涉及两个字符串,可能要使用双指针法?哈希表不太熟悉,看视频吧。
创建一个26位的数组充当哈希表,第一遍遍历字符串s,将出现的字母的次数存储到对应的hash数组的位置上,然后遍历第二个字符串对数组做减法操作,如果最后hash数组里都是0,那就是有效的字母异位词。
具体实现中需要注意hash数组的初始化必须为0.
然后存储到对应位置可以直接用字母减法,因为程序会自动用ascii码做减法。
其他的没啥,很简单的一道题,感觉没有涉及到哈希表的本质,只是对数组的灵活应用。
class Solution {
public:
bool isAnagram(string s, string t) {
int hash[26];
for(int i=0; i<26; i++){
hash[i]=0;
}
for(int i=0;i<s.size();i++){
hash[s[i]-'a']++;
}
for(int i=0;i<t.size();i++){
hash[t[i]-'a']--;
}
for(int i=0;i<26;i++){
if(hash[i]!=0){
return false;
}
}
return true;
}
};
20分钟
视频链接:
https://programmercarl.com/0024.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9.html
感觉跟上一道题一样,创建一个长度1000的数组,然后同时遍历两个数组,用长度最小的数组作为界限,然后如果value相同就在hash表里加1.
看完后发现自己对题目理解有些偏差。这里的相交只需要数组里有相同的value就算相交,不需要位置也对应上。所以如果用数组做的话需要考虑数组里的value是否有finite的,不然如果非常大的话用数组需要创建一个很大的空间,可能是稀疏的空间,非常不划算。所以介绍了用unordered_set的方法,这个数据结构非常方便,可以自动去重,并且可以直接用数组初始化。
注意使用unordered_set的语法,定义初始化的时候其实跟vector比较像,可以直接用数组初始化,然后find函数在没找到的情况下返回unordered_set::end。具体的可以参考下面的代码。
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
std::unordered_set<int> hash(nums1.begin(), nums1.end());
std::unordered_set<int> result;
for(int num:nums2){
if(hash.find(num)!=hash.end()){
result.insert(num);
}
}
return vector<int>(result.begin(), result.end());
}
};
27分钟
视频链接:
https://programmercarl.com/0024.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9.html
难点在于如何判断是否会为1,也就是说必须要变成1,100,1000,10000,也就是10的n次方才行,也就是0到9是个数字的平方,分别为0 1 4 9 16 25 36 49 64 81这几个数的各种排列组合的加和。具体的看视频吧,看看怎么用到hash表的。
非常巧妙的考察了对题目的理解,什么时候return false,显然是在sum重复出现的情况下,所以没有必要对题目进行上述的愚蠢的数学分析,直接简单粗暴的用unordered_set去判断是否存在重复的sum即可。
注意一下怎么取某个数的单位即可,其他的还是set哈希表的基本操作。
class Solution {
public:
int getSum(int n){
int sum{0};
while(n){
sum += ((n%10)*(n%10));
n = n/10;
}
return sum;
}
bool isHappy(int n) {
std::unordered_set<int> sums;
while(1){
n = getSum(n);
if(n == 1){
return true;
}
else{
if(sums.find(n)!=sums.end()){
return false;
}
else{
sums.insert(n);
}
}
}
}
};
27分钟
视频链接:
https://programmercarl.com/0024.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9.html
想到会用hash表,应该是用哈希表查找的键值存储value,然后用另一个哈希表中的value存储数组中对应的下标。
主要学习了map的操作手法,map是查找一个key在不在表里。然后只需要遍历数组,遍历到一个数先去哈希表里查,查到了就返回下标得到两数之和,没查到就把这个数存进去。
注意一下map的插入和取值以及找值的操作即可。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
std::unordered_map<int, int> hash;
for(int i=0;i<nums.size();i++){
auto iter = hash.find(target-nums[i]);
if(iter!=hash.end()){
return {iter->second, i};
}
else{
hash.insert(pair(nums[i],i));
}
}
return {};
}
};
8分钟