题目:242.有效的字母异位词
Leetcode原题:242. 有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram"
输出: true
示例 2:
输入: s = "rat", t = "car"
输出: false
提示:
1 <= s.length, t.length <= 5 * 104
s 和 t 仅包含小写字母
思考历程与知识点:
如果一个字母一个字母的找,也就是暴力,用两个for的话时间复杂度是O(N^2);
我们可以换个思路,a~z一共26个字母,我们开一个长度26的数组 f,把每个字母出现的次数记录下来, a 就是 f [0], b 就是 f [1],c就是 f [2] , 依此类推,第二个字符串也是同样开一个26的数组 f2 [ ]。最后只需要对比两个数组里的次数是否都相同就可以了。
题解:
class Solution { public: bool isAnagram(string s, string t) { int f[26]={0},f2[26]={0}; if(s.size()!=t.size())return false;// 长度不一样的话,肯定不对 for(int i = 0; i < s.size(); i++) { f[s[i] - 'a']++; f2[t[i] - 'a']++; } for(int i = 0; i < 26; i++) { if(f[i] != f2[i]) return false; } return true; } };
题目:349. 两个数组的交集
Leetcode原题:349. 两个数组的交集
给定两个数组 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] 也是可通过的
提示:
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
思考历程与知识点:
题目很简单,求集合,用数组可以做,但我们尝试学习set的方法来完成。
介绍今天要学习的新东西:unordered_set.
unordered_set: 无序set, set里的值不能重复。
unordered_set用在这个去重的题目里就特别合适了,,可以直接把重复值去掉。
具体如何使用看下面题解应该就明白了。
题解:
class Solution { public: vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { unordered_set<int> res; // 存放结果,之所以用set是为了给结果集去重 unordered_set<int> nums_set(nums1.begin(), nums1.end());//把nums1再存为 unordered_set.因为vector没有find函数。 for (int i=0;i<nums2.size();i++) { // 发现nums2的元素 在nums_set里又出现过 if (nums_set.find(nums2[i]) != nums_set.end()) { res.insert(nums2[i]);在res结果数组中插入数字 } } return vector<int>(res.begin(), res.end()); } };
题目:202题. 快乐数
Leetcode原题:202. 快乐数
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
示例 1:
输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
示例 2:
输入:n = 2
输出:false
提示:
1 <= n <= 231 - 1
思考历程与知识点:
题目特意说明,可能会无限循环,也就是sum和可能相等,所以需要记录sum,当重复的时候进行退出。
题解:
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; } } };
题目:1. 两数之和
Leetcode原题链接:1. 两数之和(Leetcode的第一道题)
给定一个整数数组 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]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
思考历程与知识点:
如果暴力来做,两个for,时间复杂度O(N^2),这里我们还是尝试学习进行优化。
新知识点:map。
map: 可以看做是一个动态数组,类似于vector<int> a, 但是map[n] 会根据n的大小进行自动排序。n可以为int, 也可以是string等其他类型,这是数组做不到的。后续做到字符串的题时我们会用到这个特性。
创建一个空map, 并遍历一遍数组。每次都在map中找,是否有相应的数字,如果没有就把数字和对应下标加进map里,进行下一个数字的查找。
为什么不干脆先把所有的数字和下标全存进map再进行查找,而是先建立空map再一个一个的把不符话的数字存进map呢?
因为题目说了,不能包括自己。如果全部先存进map,那么遇到5+5=10这种情况,即使只有1个5,它仍然遍历成功,因为确实找到了5呀,所以为了避免这种情况,每次都先查找再加入当前数字,保证当前这个数字不会被查找到。
题解:
class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { 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 {}; } };