代码随想录算法训练营第6天|242.有效的字母异位词、349. 两个数组的交集、 202. 快乐数 、 1. 两数之和
242.有效的字母异位词
首先需要解释一个名词,字母异位词:如果两个字符串中每个字符出现的次数都相同,则称这两个互为字母异位词。根据题目描述,可以使用哈希表统计在每个单词中出现字母的个数,然后在另一个单词上进行比较,之后再看哈希表是否都是为零。
class Solution {
public:
bool isAnagram(string s, string t) {
// use array as a hash table
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. 两个数组的交集
题目是求交集,又因为输出结果的每一个元素都是唯一的,因此就是需要对输出的结果进行去重,而且可以不考虑输出结果的顺序。
如果使用暴力解法,可以使用两层循环,第一层选,第二层在另一个数组里面去找,时间复杂度是O(n^2); 然后想到的就是使用哈希表来进行,因为在本题中,将数值的大小限制在[0, 1000]中,又因为输入的都是整数,所以可以不考虑存在小数的情况,因此是在有限的集合里面,可以使用哈希表
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
// for duplicate removal
unordered_set<int> result_set;
int hash[1000] = {0};
for (int num : nums1) {
hash[num] = 1;
}
for (int num : nums2) {
if (hash[num] == 1) {
result_set.insert(num);
}
}
return vector<int>(result_set.begin(), result_set.end());
}
};
如果没有限制数值的大小,因此无法使用数组来做哈希表,另外考虑到如果数值比较少,分散的比较分散,使用数组就会对空间造成极大的浪费。当然如果是比较少的数据就可以考虑哈希,不能什么都直接用 set ,因为 set 占用的空间比数组大,而且由于 set 需要将值映射到关键值 key 上需要进行哈希计算,所以速度会更慢一点。
这个时候就可以考虑使用另一个数据结构 set, 常用的有 std::set、std::multiset、std::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 not found
if (nums_set.find(num) != nums_set.end()) {
result_set.insert(num);
}
}
return vector<int> (result_set.begin(), result_set.end());
}
};
202. 快乐数
对于整数,无限重复这个过程,求平方和。因为某些数字是会重复出现的,这个时候就能指导,它永远到不了1,因此就要及时止损,跳出循环; 对于第一次出现的数字,就插入它。可以考虑使用 set 进行去重。
class Solution {
public:
int getSum(int n) {
int sum = 0;
while (n != 0) {
sum += (n % 10) * (n % 10);
n /= 10;
}
return sum;
}
bool isHappy(int n) {
unordered_set<int> sum_set;
while (1) {
int sum = getSum(n);
if (sum == 1) {
return true;
}
// not found
if (sum_set.find(sum) == sum_set.end()) {
sum_set.insert(sum);
} else {
return false;
}
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};
}
}
}
//not found
return {};
}
};
除了暴力穷举法,对于查询一个元素是否在元素中,完全可以第一时间考虑到哈希表,这里可以使用 map 这个 key-value 数据结构,使用 key来存元素,value来存下标。
这里需要注意的就是一些方法的使用,例如auto iter = map.find(a)、以及map.insert(pairs<int, int>(a, b))、 还有 iter->second
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]);
//is found
if (iter != map.end()) {
return {iter->second, i};
}
map.insert(pairs<int, int>(nums[i], i));
}
return {};
}
};