哈希表算法练习

1. 有效的字母异位词

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

示例 1: 
输入: s = "anagram", t = "nagaram" 
输出: true

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

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

代码如下:

点击查看代码
#include <iostream>
#include <unordered_map>
using namespace std;

bool IsSameWord(const string s, const string t)
{
    if (s.size() != t.size() || !s.size()) return false;
    unordered_map<char, int> map;
    for (int i = 0; i < s.size(); ++i)
    {
        ++map[s[i]];
        --map[t[i]];
    }

    for (const auto& m : map)
    {
        if (m.second) return false;
    }

    return true;
}

int main()
{
    string s = "anagram", t = "nagaram";
    cout << IsSameWord(s, t) << endl;
    return 0;
}

2. 两个数组的交集

给定两个数组,编写一个函数来计算它们的交集。

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

示例 2:
输入:nums1=[4,9,5],nums2=[9,4,9,8,4]
输出:[9,4]

说明: 输出结果中的每个元素一定是唯一的。 我们可以不考虑输出结果的顺序。

代码如下:

点击查看代码
#include<iostream>
#include<unordered_set>
#include<vector>
using namespace std;

vector<int> findCrossArr(const vector<int>& nums1, const vector<int>& nums2)
{  
    unordered_set<int> set(nums1.begin(), nums1.end());
    unordered_set<int> ans;
    for (const auto& n : nums2)
    {
        if (set.count(n))
            ans.insert(n);
    }
    return vector<int>(ans.begin(), ans.end());
}

void showArr(const vector<int>& nums)
{
    cout << '[';
    for (int i = 0; i < nums.size(); ++i)
    {
        cout << nums[i];
        if (i != nums.size() - 1)
            cout << ',';
    }
    cout << ']' << endl;
}

int main()
{
    vector<int> nums1 = {4,9,5};
    vector<int> nums2 = {9,4,9,8,4};
    showArr(findCrossArr(nums1, nums2));
    return 0;
}

3. 快乐数

编写一个算法来判断一个数 n 是不是快乐数。

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

示例:
输入:19
输出:true
解释:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1

代码如下:

点击查看代码
#include<iostream>
#include<cmath>
#include<unordered_set>
using namespace std;

/*
    这道题目使用哈希法,来判断这个sum是否重复出现,
    如果重复了就是return false, 否则一直找到sum为1为止。
*/
bool IsHappyNumber(int n)
{
    int sum = 0;
    string num = to_string(n);
    unordered_set<int> set;
    
    while (1)
    {
        sum = 0;
        for (auto n : num)
        {
            sum += pow((n - '0'), 2);
        }
        
        if (sum == 1)
            return true;
        if (set.count(sum)) 
            return false;

        set.insert(sum);
        num = to_string(sum);
    }
}

int main()
{
    int n;
    cin >> n;
    string ans = IsHappyNumber(n) ? "true" : "false";
    cout << ans << endl;
    return 0;
}

4. 两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

代码如下:

点击查看代码
#include"../tools.h"
#include<unordered_map>
vector<int> findSumIndex(const vector<int>& nums, const int target)
{
    unordered_map<int, int> map;
    // 遍历当前元素,并在map中寻找是否有匹配的key
    for (int i = 0; i< nums.size(); ++i)
    {   
        if(map.find(target - nums[i]) != map.end())
            return {i, map.find(target - nums[i])->second};
        // 如果没找到匹配对,就把访问过的元素和下标加入到map中(避免了元素重复使用)
        map[nums[i]] = i;
    }
    return {};
}

int main()
{
    vector<int> nums = {3,2,4};
    int target = 6;
    showArr(findSumIndex(nums, target));
    return 0;
}

5. 四数相加II

给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。
为了使问题简单化,所有的 A, B, C, D 具有相同的长度 N,且 0 ≤ N ≤ 500 。
所有整数的范围在 -2^28 到 2^28 - 1 之间,最终结果不会超过 2^31 - 1 。

例如:
输入:
    A = [ 1, 2]
    B = [-2,-1]
    C = [-1, 2]
    D = [ 0, 2]
输出:
    2

解释:
两个元组如下:
(0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
(1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0

代码如下:

点击查看代码
#include"../tools.h"
#include<unordered_map>

int findFourArrSum(const vector<int>& num1, const vector<int>& num2, 
    const vector<int>& num3, const vector<int>& num4)
{
    int count = 0;
    unordered_map<int, int> map;
    // 记录和次数
    for (const auto& n1 : num1)
    {
        for (const auto& n2 : num2)
        {
            ++map[n1 + n2];
        }
    }
    // 匹配和为 0
    for (const auto& n3 : num3)
    {
        for (const auto& n4 : num4)
        {
            if (map.find(0 - (n3 + n4)) != map.end())
                count += map[0 - (n3 + n4)];
        }
    }
    return count;
}

int main()
{
    vector<int> A = {1,2};
    vector<int> B = {-2,-1};
    vector<int> C = {-1,2};
    vector<int> D = {0,2};

    cout << findFourArrSum(A, B, C, D) << endl;
    return 0;
}

6. 赎金信

给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,
判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。
如果可以构成,返回 true ;否则返回 false。

(题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,
组成单词来表达意思。杂志字符串中的每个字符只能在赎金信字符串中使用一次。)

注意:
你可以假设两个字符串均只含有小写字母。

canConstruct("a", "b") -> false
canConstruct("aa", "ab") -> false
canConstruct("aa", "aab") -> true

代码如下:

点击查看代码
#include"../tools.h"
#include<unordered_map>

bool canConstruct(const string& ran, const string& mag)
{
    if (ran.size() > mag.size())
        return false;
        
    unordered_map<char, int> map;
    for (const auto& c : mag)
        ++map[c];

    for (const auto& c : ran)
    {
        if(!map.count(c) || --map[c] < 0)
            return false;
    }
    return true;
}

int main()
{
    string ran = "aa", mag = "ab";
    cout << canConstruct(ran, mag) << endl;
    return 0;
}

7. 三数之和

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?
请你找出所有满足条件且不重复的三元组。
注意: 答案中不可以包含重复的三元组。

示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4]
满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]

代码如下:

点击查看代码
#include"../tools.h"
#include<unordered_map>

vector<vector<int>> findThreeSum(vector<int>& nums)
{
    vector<vector<int>> ans;
    // 排序
    sort(nums.begin(), nums.end());
    for (int i = 0; i < nums.size(); ++i)
    {   
        // 无负数大于 0
        if (nums[i] > 0)
            return ans;
        // 前者去重
        if (i > 0 && nums[i] == nums[i - 1])
            continue;
        // 双指针
        int left = i + 1;
        int right = nums.size() - 1;
        while (right > left)
        {
            if (nums[i] + nums[left] + nums[right] > 0) --right;
            else if (nums[i] + nums[left] + nums[right] < 0) ++left;
            else
            {
                ans.emplace_back(vector<int>({nums[i], nums[left], nums[right]}));
                // 导入后,后两者去重
                while (right > left && nums[right] == nums[right - 1]) --right;
                while (right > left && nums[left] == nums[left + 1]) ++left;
                // 对准不重复的
                --right;
                ++left;
            }
        }
    }
    return ans;
}

int main()
{
    vector<int> nums = {-1, 0, 1, 2, -1, -4};
    showArr2D(findThreeSum(nums));
    return 0;
}

8. 四数之和

给定一个包含 n 个整数的数组 nums 和一个目标值 target,
判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?
找出所有满足条件且不重复的四元组

示例:
给定数组 nums = [1, 0, -1, 0, -2, 2], target = 0
满足要求的三元组集合为: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]

代码如下:

点击查看代码
#include"../tools.h"
#include<unordered_map>

vector<vector<int>> findFourSum(vector<int>& nums, int target)
{
    vector<vector<int>> ans;
    // 排序
    sort(nums.begin(), nums.end());
    for (int i = 0; i < nums.size(); ++i)
    {   
        // 正数提前剪枝
        if (nums[i] > target && nums[i] >= 0)
            break;
        // 前者去重
        if (i > 0 && nums[i] == nums[i - 1])
            continue;
        for (int j = i + 1; j < nums.size(); ++j)
        {
            if (nums[i] + nums[j] > target && nums[i] + nums[j] >= 0)
                break;
            if (j > i + 1 && nums[j] == nums[j - 1])
                continue;
            // 双指针
            int left = j + 1;
            int right = nums.size() - 1;
            while (right > left)
            {
                if ((long)nums[i] + nums[j] + nums[left] + nums[right] > target) --right;
                else if ((long)nums[i] + nums[j] + nums[left] + nums[right] < target) ++left;
                else
                {
                    ans.emplace_back(vector<int>({nums[i], nums[j], nums[left], nums[right]}));
                    // 导入后,后两者去重
                    while (right > left && nums[right] == nums[right - 1]) --right;
                    while (right > left && nums[left] == nums[left + 1]) ++left;
                    // 对准不重复的
                    --right;
                    ++left;
                }
            }
        }
        
    }
    return ans;
}

int main()
{
    vector<int> nums = {1, 0, -1, 0, -2, 2};
    int target = 0;
    showArr2D(findFourSum(nums, target));
    return 0;
}
posted @   bok_tech  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
  1. 1 翻云覆雨 BLL
  2. 2 与我无关 阿冗
  3. 3 想去海边 夏日入侵企划
  4. 4 没有理想的人不伤心 新裤子
  5. 5 生活因你而火热 新裤子
没有理想的人不伤心 - 新裤子
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.
点击右上角即可分享
微信分享提示