242. 有效的字母异位词
自己的想法
bool isAnagram(string s, string t) {
unordered_map<char,int>st1,st2;
for(char &ch: s){
st1[ch]++;
}
for(char &ch: t){
st2[ch]++;
}
if(st1.size()!=st2.size()){
return false;
}
for(int i=0;i<st1.size();i++){
if(st1[i]==st2[i]){
continue;
}
else{
return false;
}
}
return true;
}
代码随想录的想法
bool isAnagram(string s, string t) {
int record[26] = {0};//使用数组表示哈希表 大小为26 ,初始化为0,字符a映射为0,字符z映射为25
for (int i = 0; i < s.size(); i++) {//将s中字符出现的次数统计在数组中
record[s[i] - 'a']++;
}
for (int i = 0; i < t.size(); i++) {//t中字符出现一次就减少一次
record[t[i] - 'a']--;
}
for (int i = 0; i < 26; i++) {
if (record[i] != 0) {//如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
return false;
}
}
return true;// record数组所有元素都为零0,说明字符串s和t是字母异位词
}
349. 两个数组的交集
使用count,返回的是被查找元素的个数。如果有,返回1;否则,返回0。注意,map中不存在相同元素,所以返回值只能是1或0。使用find,返回的是被查找元素的位置,没有则返回map.end()。
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_map<int,int>s1,s2;
vector<int> res;
for(int &x:nums1){
s1[x]++;
}
for(int &x:nums2){
s2[x]++;
}
for(auto it=s1.begin();it!=s1.end();it++)
{
if(s2.count(it->first)){//用count不用find?
res.push_back(it->first);
}
}
return res;
}
代码随想录
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> result_set; // 存放结果,之所以用set是为了给结果集去重
unordered_set<int> nums_set(nums1.begin(), nums1.end());
for (int num : nums2) {
// 发现nums2的元素 在nums_set里又出现过
if (nums_set.find(num) != nums_set.end()) {//下标不是最后的 说明找到了
result_set.insert(num);
}
}
return vector<int>(result_set.begin(), result_set.end());//将哈希表转换为数组的形式
}
202. 快乐数
题目中说了会
无限循环,那么也就是说
求和的过程中,sum会重复出现,如果重复了就是return false, 否则一直找到sum为1为止。
unordered_set<int> set;
bool isHappy(int n) {
unordered_set<int> set;
while(1) {
int sum = 0;
while (n) {
sum += (n % 10) * (n % 10);
n /= 10;
}
if (sum == 1) {
return true;
}
if (set.count(sum)) {// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false
return false;
}
else {
set.insert(sum);
}
n = sum;//忘记更新
}
}
unordered_map<int,int> set;
bool isHappy(int n) {
unordered_map<int,int> set;
while(1) {
int sum = 0;
while (n) {
sum += (n % 10) * (n % 10);
n /= 10;
}
if (sum == 1) {
return true;
}
if (set.count(sum)) {// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false
return false;
}
else {
set[sum]++;
}
n = sum;//忘记更新
}
}
1. 两数之和
错误解法:看到求两数字之和首先想到的是“方向相反的两个指针经常用于求排序数组两数之和”,于是想到先排序再使用双指针。但是存在一个问题:返回的下标是经过排序后的下标,于是需要一个数据结构记录这个映射。我选择的是哈希表,使用哈希表记录这个映射的话,是不允许有重复元素的;或者说,有新的重复元素是会将原来映射覆盖的,于是有些测试用例便跑不过。
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int>s;//允许重复 但是重复元素 是覆盖的
for(int i=0;i<nums.size();i++){//key数值 value数组的下标
s[nums[i]]=i;
}
sort(nums.begin(),nums.end());
int left=0,right=nums.size()-1;
while(left<right){
if(nums[left]+nums[right]>target){
right--;
}
else if(nums[left]+nums[right]<target){
left++;
}
else{
//return {left,right};//但是这个时候返回的是经过排序后数组的下标 所以要想使用这个方法需要一个原数组与现在数组的一个映射
if(s.count(nums[left])&&s.count(nums[right])){
return {s[nums[left]],s[nums[right]]};
}
}
}
return {-1,-1};
}
双指针正确写法
vector<int> twoSum(vector<int>& nums, int target) {
vector<pair<int, int>> arr(nums.size());//将数组的数值与其下标以数值对的形式存储在容器中
int l = 0, r = nums.size() - 1;
for(int i=0;i<nums.size();i++)
arr[i] = {nums[i], i};
sort(arr.begin(), arr.end());
while(l<r){
if(arr[l].first + arr[r].first < target)
l++;
else if(arr[l].first + arr[r].first > target)
r--;
else
return {arr[l].second, arr[r].second};
}
return {};
}
代码随想录
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 {};
}
哈希表比较擅长给你一个元素,判断在这个集合里是否出现过
使用数组表示哈希表的情况是:key有限且比较少
使用set的情况是:数值分布很分散