UVA - 1152 4 Values whose Sum is 0(hash || 二分)

博客讲述了如何解决一道编程竞赛题目,要求在四个集合中找到四个数使得它们的和为0。博主分析了暴力枚举会超时,提出了使用二分查找和哈希表的方法,其中二分查找的复杂度为O(n^2logN),哈希表实现的复杂度在最坏情况下为O(n^2*N)。博主分享了二分查找和哈希实现的代码,并指出哈希函数的设计对于效率至关重要。
摘要由CSDN通过智能技术生成

题目传送门

题意

给四个集合,每个集合的元素个数小于4000,其中每个集合中的元素都是整数,让您求在这四个集合中各取一个数使的四个数的和为0.

分析

数据范围 如果用暴力枚举多有的可能性需要1e12的计算量肯定超时。利用中途相遇的思想可以分别枚举两个集合的所有可能性,然后从得到的两个结果集合中找,利用先排序然后二分查找可以达到n^2logn的复杂度。也可以自己实现一个hash表来统计。

二分

二分代码清晰,可以利用库中的函数使代码编写十分方便。容易理解。

for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            sum[num++] = A[i] + B[j];
    sort(sum, sum + num);
    long long cnt = 0;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cnt += upper_bound(sum, sum + num, -C[i]-D[j]) - lower_bound(sum, sum + num, -C[i] - D[j]);

hash实现

先上代码

//在hash表中插入数据, 其中idx全局变量每个测试例赋值1,也可以在hash数组开的足够大且存的数据不会溢出的时候不初始化
void insert(int summ)
{
    int temp = summ > 0 ? summ : -summ;
    int h = (temp%MAXN + temp / MAXN) % MAXN;
    sum[idx] = summ;
    pre[idx] = Hash[h];
    Hash[h] = idx++;
}

//在查询表中查询数据
int find(int summ)
{
    int cnt = 0;
    int temp = summ > 0 ? summ : -summ;
    int h = (temp%MAXN + temp / MAXN) % MAXN;
    int u = Hash[h];
    while (u)
    {
        if(sum[u] == summ)
            cnt++;
        u = pre[u];
    }
    return cnt;
}

其中的hash函数是我参考其他人的hash实现,所以就有一个缺点就是如果参数为负数的时候需要转为正数,然后在存的时候存原来的数据;

复杂度分析

二分的复杂度

利用二分的复杂度很容易分析,主要计算在一下代码中

for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)//O(n^2)
                cnt += upper_bound(sum, sum + num, -C[i]-D[j]) - lower_bound(sum, sum + num, -C[i] - D[j]);     //O(logN)

代码中注释处写了复杂度,所以全局复杂度大概是O(n^2logN);其中n是集合中元素的个数,N是sum中元素的个数,无法确定。

利用hash实现的复杂度

当使用hash表来存的时候由于查询的时候可能复杂度略小;

for (int i = 0; i <
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值