刷题第七天,454.四数相加、383. 赎金信 、15. 三数之和 、18. 四数之和

454.四数相加,利用哈希表查询简单的优点,化简时间复杂度,可以两组凑一对将其和存在哈希表中,在利用补数进行查询即可,此时时间复杂度为O(n^2),空间复杂度为O(1)。代码如下:

#include <iostream>
#include <vector>
#include <unordered_map>

int fourSumCount(std::vector<int> &A, std::vector<int> &B, std::vector<int> &C, std::vector<int> &D)
{
    std::unordered_map<int, int> sumAB; // 存储A和B所有可能和的次数
    int count = 0;

    // 计算A和B所有可能的和,并记录每个和出现的次数
    for (int a : A)
    {
        for (int b : B)
        {
            sumAB[a + b]++;
        }
    }

    // 计算C和D所有可能的和,并查找是否有相反数存在
    for (int c : C)
    {
        for (int d : D)
        {
            int sumCD = c + d;
            // 如果sumAB中存在与C和D的和相反的数,则存在符合条件的四元组
            if (sumAB.count(-sumCD))
            {
                count += sumAB[-sumCD];
            }
        }
    }

    return count;
}

int main()
{
    std::vector<int> A = {1, 2};
    std::vector<int> B = {-2, -1};
    std::vector<int> C = {-1, 2};
    std::vector<int> D = {0, 2};
    std::cout << "Total tuples: " << fourSumCount(A, B, C, D) << std::endl;
    return 0;
}

383. 赎金信,和242.有效的字母异位词 (opens new window)很像,但是不能重复,可以用哈希表简单实现,代码如下:

#include <iostream>
#include <unordered_map>
#include <string>

bool canConstruct (const std::string& string1,const std::string& string2){
    std::unordered_map<char,int> charcount;

    for(char s:string1){
        charcount[s]++;
    }
    for(char t:string2){
        if(charcount[t] == 0){
            return false;
        }else{
            charcount[t]--;
        }
    }
    return true;
}

int main(){
    std::string ransomNote = "aa";
    std::string magazine = "aab";
    if (canConstruct(magazine,ransomNote)) {
        std::cout << "true" << std::endl;
    } else {
        std::cout << "false" << std::endl;
    }
    return 0;
}

15. 三数之和,与上述题型中只需返回组合个数的题型不同,此题需要返回所有组合并去重,因此简单使用哈希表并不能简单求解该问题,需要利用双指针来求解题目,并设计合理的去重检测,代码如下:

#include <iostream>
#include <vector>
#include <algorithm>

std::vector<std::vector<int>> threeSum(std::vector<int> &nums)
{
    std::sort(nums.begin(), nums.end());
    std::vector<std::vector<int>> res;

    for (int i = 0; i < nums.size(); ++i)
    {
        if (i > 0 && nums[i] == nums[i - 1]) // 每回合都把一个数确定的可能性包括了,所以有一样的直接pass
        {
            continue;
        }

        int left = i + 1, right = nums.size() - 1;
        while (left < right)
        {
            int sum = nums[i] + nums[left] + nums[right];
            if (sum == 0)
            {
                res.push_back({nums[i], nums[left], nums[right]});   // 往容器中放的时候注意加{}
                while (left < right && nums[left] == nums[left + 1]) // 如果左边和上一个一样,那么直接跳过,因为确定两个数的情况下,第三个数是确定的
                {
                    left++;
                }
                while (left < right && nums[right] == nums[right - 1]) // 和上面同理
                {
                    right--;
                }
                left++;
                right--;
            }
            else if (sum < 0)
            {
                left++;
            }
            else
            {
                right--;
            }
        }
    }
    return res;
}

int main()
{
    std::vector<int> nums = {-1, 0, 1, 2, -1, -4};
    std::vector<std::vector<int>> result = threeSum(nums);
    for (const auto &triplet : result)
    {
        std::cout << "[" << triplet[0] << ", " << triplet[1] << ", " << triplet[2] << "]\n";
    }
    return 0;
}

18. 四数之和,和上一道题目原理相同,只不过多加了一层for循环来实现,代码如下:

#include <iostream>
#include <vector>
#include <algorithm>

std::vector<std::vector<int>> fourSum(std::vector<int> &nums, int target)
{
    std::vector<std::vector<int>> res;
    if (nums.size() < 4)
        return res;
    std::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; // 跳过重复的数

            int left = j + 1, right = nums.size() - 1;
            while (left < right)
            {
                int sum = nums[i] + nums[j] + nums[left] + nums[right];
                if (sum == target)
                {
                    res.push_back({nums[i], nums[j], nums[left], nums[right]});
                    while (left < right && nums[left] == nums[left + 1])
                        left++; // 跳过重复的数
                    while (left < right && nums[right] == nums[right - 1])
                        right--; // 跳过重复的数
                    left++;
                    right--;
                }
                else if (sum < target)
                {
                    left++;
                }
                else
                {
                    right--;
                }
            }
        }
    }

    return res;
}

int main()
{
    std::vector<int> nums = {1, 0, -1, 0, -2, 2};
    int target = 0;
    std::vector<std::vector<int>> result = fourSum(nums, target);
    for (const auto &quad : result)
    {
        std::cout << "[" << quad[0] << ", " << quad[1] << ", " << quad[2] << ", " << quad[3] << "]\n";
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值