LeetCode【代码随想录】刷题(哈希表篇)

242.有效的字母异位词

力扣题目链接

题目:给定两个字符串 st ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 st 中每个字符出现的次数都相同,则称 st 互为字母异位词。

思路:哈希表,用unordered_map(底层是哈希表实现)存储字母及其出现次数。由于仅是字母,其实开一个26长度的数组也行。

通过代码:

class Solution {
public:
    bool isAnagram(string s, string t) {
        unordered_map<char, int> map;
        for(int i = 0; i < s.length(); i++)
            map[s[i]] += 1;
        for(int i = 0; i < t.length(); i++)
            map[t[i]] -= 1;
        for(auto c: map)
        {
            if(c.second != 0)
                return false;
        }
        return true;
    }
};

349. 两个数组的交集

力扣题目链接

题目:给定两个数组 nums1nums2 ,返回 它们的交集。输出结果中的每个元素一定是唯一 的。我们可以不考虑输出结果的顺序 。

思路:将其中一个数组的元素全部放进哈希表里,遍历第二个数组,查询是否在表里出现。

通过代码:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result;
        unordered_set<int> s(nums1.begin(), nums1.end());
        for(int i = 0; i < nums2.size(); i++)
        {
            if(s.find(nums2[i]) != s.end())
                result.insert(nums2[i]);
        }
        return vector<int>(result.begin(), result.end());
    }
};

202.快乐数

力扣题目链接

题目:编写一个算法来判断一个数 n 是不是快乐数。「快乐数」 定义为:

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

如果 n 是 快乐数 就返回 true ;不是,则返回 false

思路:能出现无限循环的情况一定是平方和会重复出现,用一个哈希表存一下就行,如果能在表里查到,说明会一直循环下去,不是快乐数。

通过代码:

class Solution {
public:
    int happy(int n)
    {
        int res = 0;
        while(n)
        {
            res += pow(n % 10, 2);
            n /= 10;
        }
        return res;
    }
    bool isHappy(int n) {
        unordered_set<int> hash;
        while(1)
        {
            int hp = happy(n);
            if(hp == 1)
                return true;
            if(hash.find(hp) != hash.end())
                return false;
            else
                hash.insert(hp);
            n = hp;
        }
    }
};

1. 两数之和

力扣题目链接

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

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

思路:用unordered_map把已经遍历过的数据存起来,key是数组的值,value是对应的索引。遍历的时候在表里查找target-当前值,若存在即可返回。

通过代码:

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

454.四数相加II

力扣题目链接

题目:给你四个整数数组 nums1nums2nums3nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:

  • 0 <= i, j, k, l < n
  • nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

思路:nums1和nums2一组,用一个unordered_map存放它们的和及其次数;nums3和nums4一组,在map里查找-(nums3[i]+nums4[j])即可。

通过代码:

class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        int cnt = 0;
        unordered_map<int, int> ab;
        for(int i = 0; i < nums1.size(); i++)
            for(int j = 0; j < nums2.size(); j++)
                ab[nums1[i] + nums2[j]] += 1;
        for(int i = 0; i< nums3.size(); i++)
            for(int j = 0; j < nums4.size(); j++)
            {
                auto iter = ab.find(-(nums3[i] + nums4[j]));
                if(iter != ab.end())
                    cnt += iter -> second;
            }
        return cnt;     
    }
};

383. 赎金信

力扣题目链接

题目:给你两个字符串:ransomNotemagazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。如果可以,返回 true ;否则返回 falsemagazine 中的每个字符只能在 ransomNote 中使用一次。

思路:用一个map记录有哪些字符及其出现次数。

通过代码:

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        unordered_map<char, int> map;
        for(char c : magazine)
            map[c] +=1;
        for(char c : ransomNote)
        {
            if(map.find(c) == map.end())
                return false;
            map[c]--;
            if(map[c] < 0)
                return false;
        }
        return true;
    }
};

15.三数之和

力扣题目链接

题目:给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

思路:排序之后用一个指针确定第一个数的位置,剩下两个数再用双指针。

通过代码:

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;
        sort(nums.begin(), nums.end());
        for(int i = 0; i < nums.size(); i++)
        {
            if(i > 0 && nums[i] == nums[i-1])
                continue;
            int target = -nums[i], right = nums.size() - 1;
            for(int left = i + 1; left < right; left++)
            {
                if(left > i + 1 && nums[left] == nums[left - 1])
                    continue;
                while(left < right && nums[left] + nums[right] > target)
                {
                    right--;
                }
                if(left == right)
                    break;
                if(nums[left] + nums[right] == target)
                    result.push_back({nums[i], nums[left], nums[right]});
            }
        }
        return result;
    }
};

18.四数之和

力扣题目链接

题目:给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

  • 0 <= a, b, c, d < n
  • abcd 互不相同
  • nums[a] + nums[b] + nums[c] + nums[d] == target

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

思路:和三数之和类似,加一重循环即可。

通过代码:

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> result;
        if(nums.size() < 4)
            return result;
        sort(nums.begin(), nums.end());
        for(int i = 0; i < nums.size() - 3; i++)
        {
            if(i > 0 && nums[i] == nums[i - 1])
                continue;
            for(int j = i + 1; j < nums.size() - 2; j++)
            {
                if(j > i + 1 && nums[j] == nums[j - 1])
                    continue;
                long long newtarget = (long long)target - nums[i] - nums[j];
                int right = nums.size() - 1;
                for(int left = j + 1; left < right; left++)
                {
                    if(left > j + 1 && nums[left] == nums[left - 1])
                        continue;
                    while(left < right && nums[left] + nums[right] > newtarget)
                        right--;
                    if(left == right)
                        break;
                    if(nums[left] + nums[right] == newtarget)
                        result.push_back({nums[i], nums[j], nums[left], nums[right]});
                }
            }
        }
        return result;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

h0l10w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值