给定两个字符串 s
和 t
,编写一个函数来判断 t
是否是 s
的字母异位词。
注意:若 s
和 t
中每个字符出现的次数都相同,则称 s
和 t
互为字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram" 输出: true
示例 2:
输入: s = "rat", t = "car" 输出: false
思路:分析题目,两个字符串只有字母顺序改变,没有出现新的字母,这样是字母异位词。
解决:记录一下s字符串字母出现的次数,如果该字母在t字符串中出现,次数减一,最后如果所有的字母次数都是0,说明是字母异位词。
代码:
class Solution {
public:
bool isAnagram(string s, string t) {
int r[26]={0};
for(int i=0;i<s.size();i++){
r[s[i]-'a']++;
}
for(int i=0;i<t.size();i++){
r[t[i]-'a']--;
}
for(int i=0;i<26;i++){
if(r[i]!=0){
return false;
}
}
return true;
}
};
给定两个数组 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] 也是可通过的
思路:找相同的元素就行,nums1出现了,nums2如果再出现就输出;
解法:1.首先定义一个记录数字出现的数组;2.最后输出不重复的数组,这里用std::unordered_set,因为使用unordered_set 读写效率是最高的,并不需要对数据进行排序,而且还不要让数据重复。
代码:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
int h[1005]={0};
unordered_set<int> r;
for(int i=0;i<nums1.size();i++){
h[nums1[i]]=1;
}
for(int i=0;i<nums2.size();i++){
if(h[nums2[i]]==1){
r.insert(nums2[i]);
}
}
return vector<int>(r.begin(),r.end());
}
};
编写一个算法来判断一个数 n
是不是快乐数。
「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n
是 快乐数 就返回 true
;不是,则返回 false
。
思路:首先求各个位的数的平方,再相加;然后记录平方和,这时候可以用哈希表,和出现一次数值变1,如果再出现,说明陷入死循环,直接退出,如果最后有数字为1,返回true就行。
解决:1.设计一个获得各个位上平方和的函数;2.循环判断:①和是否为1;②是否已经出现现过;③没有出现,更新计算平方和的初值;3.需要利用unordered_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) {
unordered_set<int> r;
while(1){
int sum=getsum(n);
if(sum==1){//和最后是1,是快乐数
return true;
}
if(r.find(sum)!=r.end()){//和在r中出现过,说明陷入循环
return false;
}else{
r.insert(sum);//插入没有出现的平方和
}
n=sum;//更新新的值
}
}
};
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6 输出:[1,2]
思路:先从数组中取一个数i,那另一个数就是target-i,这时候就会有两个问题:①另一个数怎么找②找到后返回下表。
解决1:用暴力方法依次寻找可以做出来,取一个数,遍历剩余的数,如果当前的数没有找到一个合适的数,那就再取下一个数,继续遍历剩余的数,最后找到就输出两个数的下标。
代码:(时间复杂度:O(N^2))
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int n = nums.size();
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {//注意这里是从i+1开始,不要重复计算
if (nums[i] + nums[j] == target) {
return {i, j};
}
}
}
return {};
}
};
解决2:利用哈希表,遍历过的数字放在哈希表中,未遍历过的数字只要在哈希表中找到一个数相加等于目标值就可以返回下表。这里并不要求key有序,因为取到哪个数字,哪个数字就进哈希表,所以用unordered_map,key是数字,value就是数字在数组中的下标,因为最后如果找到合适两个数组就要返回下标。
代码:(时间复杂度:O(N))
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++){
int n=target-nums[i];//找到另一个合适的数
if(map.find(n)!=map.end()){//如果这个数在map中,返回下标,也就是value值
return {map.find(n)->second,i};
}
map.insert(pair<int, int>(nums[i], i));//没在就插入
}
return {};
}
};
收获:熟悉了c++中set(集合)和map(映射)和它们的应用场景,要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。最后学习一下,哈希表基础理论:代码随想录总结很好。代码随想录 (programmercarl.com)