有效的字母异位词
leetcode242
直观思路
用数组的思想来做,字母异位词意味着两个字符串数组中,所包含的字符及其出现次数是相同的,这就意味着字符串的长度相同以及若排序后各位置应该都相同(不考虑对单个字符进行次数估计的原因在于不知道存在多少个字符)。
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.length() != t.length()){
return false;
}//如果s和t长度不同,返回false
sort(s.begin(),s.end());
sort(t.begin(),t.end());//对s和t进行排序
return s == t;//返回s和t相等的情况
}
};
算法的时间复杂度为O(nlogn)(sort快排O(nlogn),比较为O(n),综上为O(nlogn)),空间复杂度为O(1)。
简易哈希表
考虑一个单词由小于等于26个字母组成,创建一个全为0的数组ivect,以a下标索引为0,b下标索引为1...以此为例。针对字符串s,遍历s,对s中出现的每个字母更新数组(ivect[i]++),之后遍历t,对t中出现的每个字母(ivect[i]--),若最后数组全为0,则为字母异位词,返回true,否则返回false。
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.length()!=t.length())//首先判断长度,若长度不同,直接返回false
return false;
vector<int> ivect(26,0);//创建长度为26的数组ivect,简易的哈希表
for(int i = 0;i<s.length();i++){//对字符串s遍历,ivect相应位置增
ivect[s[i] - 'a']++;//这里使用利用ascii码的相对位置,'a'-'a' = 0,以此类推
}
for(int j = 0;j<s.length();j++){//对字符串t遍历,ivect相应位置减
ivect[t[j] - 'a']--;
}
for(int i = 0;i < 26;i++){//若最后ivect不全为0返回false,否则返回true
if(ivect[i]!=0){
return false;
}
}
return true;
}
};
算法的空间复杂度为O(1),时间复杂度为O(n)。
两个数组的交集
考虑使用哈希表,将两个数组分别存入哈希表set1、set2,这种方式可以保证获得唯一的数组元素,之后判断哈希表中是否有元素相同,若存在相同元素,将其加入数组ivect,之后返回ivect。
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
vector<int> ivect = {};
unordered_set<int> set1, set2;
for(auto &num:nums1){//将nums1中元素存入哈希表1
set1.insert(num);
}
for(auto &num:nums2){//将nums2中元素存入哈希表2
set2.insert(num);
}
if(set1.size()>set2.size()){//判断哈希表1和哈希表2的长度,选取较短长度的哈希表
swap(set1,set2);
}
for(auto&num:set1){//判断较长哈希表中是否存在较短哈希表元素,若存在,在ivect中加入
if(set2.count(num))
ivect.push_back(num);
}
return ivect;
}
};
设两个数组长度为n和m,算法的时间复杂度为O(n+m),算法的空间复杂度为O(n)
快乐数
这里需要强调无限循环,意味着若非快乐数,则在运行过程中,会出现重复数值,这时可以考虑使用哈希表。
class Solution {
public:
int getsum(int n){//将一个数替换为它每个位置上的数字的平方和
int sum = 0;
while(n){
sum += (n%10) * (n%10);//取出个位数,将个位数求平方
n = n/10;//将该数/10,十位变个位 以此类推
}
return sum;//返回一次计算结果
}
bool isHappy(int n) {
int sum = 0;
unordered_set<int> set;//创建哈希表
sum = getsum(n);//计算结果
while(1){
if(sum == 1){
return true;//当符合sum == 1时,return True
}
if(set.count(sum)){//否则若原表中含这个数,则return false
return false;
}
set.insert(sum);//将这个数加入哈希表中
sum = getsum(sum);//重新计算一次,并进入循环
}
}
};
两数之和
暴力解法
遍历两次数组,找到两数和为target的下标索引并返回。算法时间复杂度O(n^2),空间复杂度O(1)。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int>ivect = {};
for(int i = 0; i <nums.size();i++){
int x = target - nums[i];//计算与目标的差距,在遍历中寻找
for(int j = 0; j < nums.size();j++){
if(nums[j] == x and i != j){
ivect.push_back(i);
ivect.push_back(j);
return ivect;
}
}
}
return ivect;
}
};
哈希表
这里考虑题目是当已经有一个元素,要去寻找是否存在另一个元素也在这个数组中,实现这两个元素相加为target,考虑这一要求,我们需要去查询一个元素是否在一个集合中,考虑使用哈希表。
对数组中元素遍历的过程中,计算元素与target之间的差距x,在哈希表中查找x,若存在,返回其索引和当前遍历下标;若不存在,将当前元素与其在数组中的下表索引存入哈希表中,哈希表用来存放我们已经遍历过的元素及其下标索引,关键词为元素,键值value为其索引。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
std::unordered_map<int, int> numMap; // 创建哈希表
for (int i = 0; i < nums.size(); ++i) {
int x = target - nums[i]; // 计算目标值
if (numMap.count(x)) {
// 如果找到了目标值,返回结果
return {numMap[x], i};
}
// 如果没找到,将当前元素和它的下标加入哈希表
numMap[nums[i]] = i;
}
return {}; // 如果没有找到,返回空数组
}
};
算法的时间复杂度为O(n),空间复杂度O(n),代价,用空间换时间。
1101

被折叠的 条评论
为什么被折叠?



