昨天开学,这学期课巨多,上的啥课都要课后补,高数,离散,线代,还想补周赛,备蓝桥,还有每日打卡,真的快疯掉了,,,
242.有效的字母异位词
题目内容:
给定两个字符串 s
和 t
,编写一个函数来判断 t
是否是 s
的字母异位词。
注意:若 s
和 t
中每个字符出现的次数都相同,则称 s
和 t
互为字母异位词。
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.length() != t.length()) return false;
unordered_map<char, int> a;
for(char c : s) {
a[c]++;
}
for(char c : t) {
if(--a[c] < 0) return false;
}
return true;
}
};
反思:
新学了:元素计数使用unordered_map
思路:如果两个字符串每个字符出现的次数都相同,那这两个字符串一定长度相等,不相等首先判false;在长度相等的情况下,如果两个字符串不是字母异位词,那一个字符少了的同时一定有一个字符多了,所以可以只靠--a[c]<0来判断
本来写了个数组版本的来着但是没过,代码随想录写的就是数组版本哎
349.两个数组的交集
题目内容:给定两个数组 nums1
和 nums2
,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2] 输出:[2]
我认为去重是这道题比较重要的一个操作了,我的代码如下:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> a;
vector<int> result;
for(int i : nums1) {
a.insert(i);
}
for(int i : nums2) {
if(a.find(i) != a.end()) {
result.push_back(i);
}
}
sort(result.begin(), result.end());
auto it = unique(result.begin(), result.end());
result.erase(it, result.end());
return result;
}
};
两个循环结束的后面三行代码就是在去重,因为本题不考虑输出顺序,所以先使用sort使相等元素排在了一起,再使用unique()函数把相邻的相等的元素移到了数组最后面,再使用erase()函数清除重复元素...这样做太复杂了,而unordered_set本身就有去重功能,将得到的相同元素存进unordered_set里可以自动去重,以下是代码随想录版本,总的来说,进行了两个优化:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> res;//用来存放最终交集元素
unordered_set<int> temp(nums1.begin(), nums1.end());
for(int i : nums2) {
if(temp.find(i) != temp.end()) {
res.insert(i);
}
}
return vector<int>(res.begin(), res.end());
}
};
优化1:将nums1的元素存入temp里直接存入没有使用循环,更简洁;
优化2:把nums2中与1相等的元素存入set里,自动去重
202.快乐数
数快不快乐我不知道,看完这道题的我是不快乐的...
题目内容:
编写一个算法来判断一个数 n
是不是快乐数。
「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n
是 快乐数 就返回 true
;不是,则返回 false
。
这道题知道无限循环也就是sum重复出现了很重要,我就根本没想到这一点...
缝缝补补后,我的代码如下:
class Solution {
public:
int get_sum(int n)
{
int sum = 0;
while(n) {
sum += (n%10) * (n%10);
n /= 10;
}
return sum;
}
bool isHappy(int n) {
unordered_set<int> record;
while(1) {
int sum = get_sum(n);
if(sum == 1) return true;
else if(record.find(sum) != record.end()) return false;
record.insert(sum);
n = sum;
}
}
};
反思:无限循环也就是sum重复出现了,那么如果继续循环下去一定还会再出现新的sum,所以用一个unordered_set来记录sum;由于判断sum是一个持续的过程,所以使用while循环,循环结束条件是sum等于1或者sum重复出现,无法确定什么时候结束,所以触发结束条件时直接return,while循环条件里就写1;循环里每次更新sum的值(第一次没把这行代码写进循环里!!!),判断,没有return就把该行代码加入set里,然后重新赋值sum。
1.两数之和
题目内容:
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
我的代码:
自己写了一个比较清澈的愚蠢的暴力解法,完全没有用上今日的知识点setQAQ
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int i = 0, j = 1;
vector<int> res;
for( ; i < nums.size(); i++) {
for(j = i + 1; j < nums.size(); j++) {
if(i == j) continue;
if(nums[i] + nums[j] == target) {
res.push_back(i);
res.push_back(j);
break;
}
}
}
return res;
}
};
两层嵌套循环,时间复杂度O(n^2)拉满了...
代码随想录版本:
思路是建立一个无序map,key存储数组元素,value存储元素下标,每遍历到数组的一个数字,就找找map里有没有target-该值,没有的话就将该元素及下标加入map里,有的话就输出两个下标,时间复杂度很低。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> record;
vector<int> result;
for(int i = 0; i < nums.size(); i++) {
auto it = record.find(target - nums[i]);
if(it != record.end()) {
result.push_back(it -> second);
result.push_back(i);
}else{
record.insert(pair<int, int>(nums[i], i));
}
}
return result;
}
};
反思:第一次写的时候,从map中寻找一个元素要使用迭代器!第一次循环条件也写错,直接写了(int i : nums) 这样的i表示的是nums中每个元素的值,而我需要的i是数组下标,所以还是常规写法;把元素添入map的操作今天也是第一次学,record.insert(pair<int, int>(nums[i], i));
终于补完这一篇了,,,还有链表2,哈希表2要补,,,今天还新开了字符串(累瘫)...