算法学习打卡day5|242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和

242.有效的字母异位词

力扣题目链接
题目描述:
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
示例 1: 输入: s = “anagram”, t = “nagaram” 输出: true

示例 2: 输入: s = “rat”, t = “car” 输出: false

说明: 你可以假设字符串只包含小写字母。

思路:
  该题其实是判断两个字符串的各个字母数目是否相同,很容易想到分别统计两个字符串的字母数目进行比较。
 那么,我们可以利用数组下标标识26个英文字母,然后存储每个字母的次数,首先遍历s,统计出每个字母的次数,然后遍历t,在数组中依次减去对应字母出现的次数,这样最后得到的数组如果每项都为0,即为所求结果。
代码实现:

bool isAnagram(string s, string t) {
        vector<int> record(26, 0);
        for(auto& s_word : s) {
            record[s_word - 'a']++;
        }
        for (auto& t_word : t) {
            record[t_word - 'a']--;
        }
        for (int& word : record) {
            if(word != 0) {
                return false;
            }
        }
        return true;
    }

349. 两个数组的交集

力扣题目链接
题目描述:
给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

思路:

  • 由于返回值不能包含重复元素,首先需要对一个数组进行去重,这很容易想到哈希表,又因为我们只需要key就能解决问题,而且无需排序,直接采用unordered_set,然后遍历另一个数组在unordered_set查找即可。
    代码实现:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> record1(nums1.begin(),nums1.end());
        unordered_set<int> results_set;
        vector<int> results;
        for (int& i : nums2) {
            if(record1.count(i)) {
                results_set.insert(i);
            }
        }
        return vector<int>(results_set.begin(), results_set.end());
    }

202. 快乐数

力扣题目链接
题目描述:
编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。

思路:

  • 和上题类似,难点在于需要判断是否出现重复的平方和以及取如何每位置的数字,只要重复就返回false
  • 大体思路是将每次求得的平方和判断是否为1,不是的话判断是否和之前的平方和重复,如何判断?当然是哈希表了!上面两种情况都不是的话就存到set里,然后继续循环判断。

代码实现:

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> sum_set;
        int sum = n;
        while(1) {
            sum = getSum(sum);
            cout << sum << endl;
            if(sum == 1) {
                return true;
            }
            if (sum_set.count(sum)) {
                return false;
            }
            sum_set.insert(sum);
        }
    }

1. 两数之和

力扣题目链接
题目描述:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

思路:
 由于一个元素不能重复出现,我们可以直接遍历元素,然后在哈希表中寻找,是否存在(target-当前值)这个数字,存在就直接返回,不存在可以把当前元素添加到哈希表中,因为题目要求返回下标,那么我们可以使用map的value来记录下标值。
代码实现:

vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> record;
        for (int i = 0; i < nums.size(); ++i) {
            auto iter = record.find(target - nums[i]);
            if (iter != record.end()) {
                return {iter->second, i};
            }
            record.insert(pair<int, int>(nums[i], i));
        }
        return {};
    }

总结:

  • 哈希表的常用数据结构:
    • 数组:一般情况下适用于数据量给定且不是很分散的时候,而且如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费。
    • set(set、multiset、unordered_map):
      当我们要使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的,如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset。
    • map(map、multimap、unordered_map)
      和set同理,只不过多了value
  • 哈希表的使用场景:
    1. 当需要判断一个元素是否在集合中或者一个元素是否出现过的时候
    2. 当需要去重的时候

你可能感兴趣的:(算法学习打卡,算法,学习,c++,leetcode)