leetcode链接:力扣题目链接(opens new window)
视频链接:学透哈希表,数组使用有技巧!Leetcode:242.有效的字母异位词(opens new window)‘
这题一刷就可以AC了,主要思路就是通过hashtable记录每个字符串的每个字符的出现次数,最后两次遍历后为0说明两个句子符合要求。注意点有三:
for (int count: record) {进行数组的遍历
题解:
class Solution {
public:
bool isAnagram(string s, string t) {
int alphabet[26] = {0};
for(int i = 0; i < s.length(); i++){
alphabet[s[i] - 'a']++;
}
for(int j = 0; j < t.length(); j++){
alphabet[t[j] - 'a']--;
}
for(int k = 0; k < 26; k++){
if(alphabet[k] != 0){
return false;
}
}
return true;
}
};
leetcode链接:力扣题目链接(opens new window)
视频链接:学透哈希表,set使用有技巧!Leetcode:349. 两个数组的交集 (opens new window)
给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的
这题是二刷,直接有思路了。本来的思路跟第一题一样,使用unordered_map遍历nums1的时候记录下每个元素出现的次数,遍历nums2的时候查表,只要次数大于0,说明重复,加入结果res数组中。但是最后没有AC,这是因为res中元素可能是重复的。
因此需要使用set存储最后的结果,再转化为vector,最后修改后AC了,我的代码如下:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_map<int,int> table;
set<int> res;
for(int num : nums1){
table[num]++;
}
for(int num : nums2){
if(table[num] > 0){
res.insert(num);
}
}
vector<int> res1(res.begin(),res.end());//使用迭代器构建vector。
return res1;
}
这里注意从set->vector的转化方式:
vector<int> res1(res.begin(),res.end());//使用迭代器构建vector。
然后查看题解后,发现其实并不需要unordered_map,使用unordered_set对nums1进行去重再在nums2中进行查找即可:
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> result_set; // 存放结果,之所以用set是为了给结果集去重
unordered_set<int> 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<int>(result_set.begin(), result_set.end());
}
};
这里注意if (nums_set.find(num) != nums_set.end()) {
函数,set.find()函数返回对应的迭代器,如果找不到返回end()。然后set的操作使用insert进行插入。
leetcode链接:力扣题目链接(opens new window)
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
示例 1:
输入:n = 19
输出:true
解释:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
这道题是一刷,看到的第一眼以为是个数学问题,没想过怎么用hashtable做,后来看题解才明白,可以用unordered_set存放sum的值,每次sum只要重复了说明会重蹈复辙,肯定不是快乐数,然后再找使最后的sum为1设为循环结束的条件即可。看完直接写代码然后AC了:
class Solution {
public:
long getSum(int n){//得到各位的平方和
int sum = 0;
do{
sum += (n % 10) * (n % 10);
n = n / 10;
}while(n > 0);
return sum;
}
bool isHappy(int n) {
//关键点在于判断sum是否重复出现,否则就会重蹈覆辙;
unordered_set<int> sums;
int sum = getSum(n);
while(sum != 1){
cout << sum << endl;
if(sums.find(sum) != sums.end()){
return false;
}
sums.insert(sum);
sum = getSum(sum);
}
return true;
}
};
这里需要注意的是getSum()函数,求每一位然后分别求平方,可以分离出来先调试正确。
标准题解:
class Solution {
public:
// 取数值各个位上的单数之和
int getSum(int n) {
int sum = 0;
while (n) {
sum += (n % 10) * (n % 10);
n /= 10;
}
return sum;
}
bool isHappy(int n) {
unordered_set<int> set;
while(1) {
int sum = getSum(n);
if (sum == 1) {
return true;
}
// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false
if (set.find(sum) != set.end()) {
return false;
} else {
set.insert(sum);
}
n = sum;
}
}
};
整体比我写的更连贯,都在while循环中做了。
leetcode链接:力扣题目链接(opens new window)
视频链接:梦开始的地方,Leetcode:1.两数之和 (opens new window)
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
好几次刷leetcode都止步于此。。。首先暴力解法肯定是能想到的,每遍历一个元素,都在数组中搜target - n在不在数组中,在就直接返回。可是这题安排在hashtable章节,肯定是能用hash表解决。这题之前刷过,但是思路不是很清晰,后来才想到可以使用unordered_map把之前出现的存起来。其中key是值,value是对应的下标:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> table;//key为值,value为下标
for(int i = 0; i < nums.size(); i++){
auto iter = table.find(target - nums[i]);
if(iter != table.end()){
return {iter->second,i};
}else{
table[nums[i]] = i;
}
}
return {0,0};
}
};
标准题解:
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++) {
// 遍历当前元素,并在map中寻找是否有匹配的key
auto iter = map.find(target - nums[i]);
if(iter != map.end()) {
return {iter->second, i};
}
// 如果没找到匹配对,就把访问过的元素和下标加入到map中
map.insert(pair<int, int>(nums[i], i));
}
return {};
}
};
可以看到插入两个方法都可以,insert和直接赋值。
hashtable部分的题都不算难,对我比较重要的是C++中set和map的用法,创建、插入什么的,过了一个充实的周一。