文章目录

  • 1.二分查找法
    • 1.1 思路:
    • 1.2 AC代码
  • 2.hash查找法
    • 2.1 思路:
    • 2.2 Wrong Answer 代码
    • 2.3 Time Limit Exceeded 代码
    • 2.4 偷懒失败,hash_map在poj中不存在
    • 2.5 哈希表+二叉查找树(超时)
    • 2.6 AC代码(哈希+数组法)

题目链接: http://poj.org/problem?id=2785

题目大意:给定不超过4000行4个数,每列挑出来1个,使之和为0,有多少种方案。

1.二分查找法

1.1 思路:

  • 对左边两列的所有和求出来,右边两列所有的和的求出来再取负
  • 右侧两列的值排序(进行二分查找)
  • 对左边所有的和在右边的和中进行二分查找,并查找前后都满足要求的,计数即得答案

1.2 AC代码

/*** @description: 求四个数相加等于0的组合种数* @author: michael ming* @date: 2019/5/8 22:18* @modified by:*/
#include <iostream>
#include <memory.h>
#include <algorithm>using namespace std;
int a[4001], b[4001], c[4001], d[4001];
int ab[4000*4000+1], cd[4000*4000+1];   //存储a+b,c+d
int findSameValue(int value, int maxindex)//二分查找
{int low = 0, high = maxindex, mid, index, count=0;while(low <= high){mid = low + (high - low)/2;if(value == cd[mid])    //查找前后满足要求的个数{index = mid - 1;while(index >= 0 && value == cd[index--])count++;index = mid + 1;while(index <= high && value == cd[index++])count++;return count + 1;}else if(value < cd[mid])high = mid - 1;elselow = mid + 1;}return 0;
}
int main()
{int line, k=0;cin >> line;memset(ab, 0, sizeof(ab));memset(cd, 0, sizeof(cd));for(int i = 0; i < line; ++i){cin >> a[i] >> b[i] >> c[i] >> d[i];}for(int i = 0; i < line; ++i){for(int j = 0; j < line; ++j){ab[k] = a[i]+b[j];cd[k++] = -(c[i]+d[j]);}}sort(cd,cd+k);  //二分查找的必要条件,有序int result = 0;for(int i = 0; i <= k-1; ++i)result += findSameValue(ab[i], k-1);cout << result << endl;return 0;
}

2.hash查找法

2.1 思路:

  • 对左边两列的所有和求出来,右边两列所有的和的求出来再取负
  • 对左侧两列的和存入哈希表
  • 对右边两列的和在哈希表中查找

2.2 Wrong Answer 代码

(未解决冲突,并且hash后的值可能为负,作为数组下标不行,所以错误)

/*** @description: 4个数和为0的方案数,哈希法* @author: michael ming* @date: 2019/5/9 22:30* @modified by: */
#include <iostream>
#include <memory.h>
using namespace std;
int a[4001], b[4001], c[4001], d[4001];
int ab[4000*4000+1], cd[4000*4000+1];   //存储a+b,c+d
int *hasht = new int[16000057];
int offset = 1000000000;
int hashfunc(int &value)
{int mod = 16000057;return (value%mod + value/mod)%mod;
}
int main()
{int line, k=0, value;cin >> line;memset(hasht, 0, sizeof(hasht));for(int i = 0; i < line; ++i){cin >> a[i] >> b[i] >> c[i] >> d[i];}for(int i = 0; i < line; ++i){for(int j = 0; j < line; ++j){ab[k] = a[i]+b[j];value = ab[k]+offset;hasht[hashfunc(value)]++;cd[k++] = -(c[i]+d[j]);}}int result = 0;for(int i = 0; i < k; ++i){value = cd[i]+offset;if(hasht[hashfunc(value)])result += hasht[hashfunc(value)];}cout << result << endl;delete [] hasht;return 0;
}

2.3 Time Limit Exceeded 代码

/*** @description: 4个数和为0的方案数,哈希法* @author: michael ming* @date: 2019/5/9 22:30* @modified by: */
#include <iostream>
#include <math.h>
using namespace std;
struct linkedNode   //链表节点
{pair<int, int> data;linkedNode *next;linkedNode():next(NULL), data(make_pair(0,0)){}
};
class linkedList    //链表
{public:linkedNode *head;linkedList(){head = new linkedNode();  //表头哨兵}~linkedList(){delete head;}
};
class linkedHash
{private:linkedList *htList; //散列表链表数组int bucket;  //散列表桶个数
public:linkedHash(int m):bucket(m){htList = new linkedList [bucket] ();}~linkedHash(){for(int i = 0; i < bucket; ++i){linkedNode *p = htList[i].head->next, *q = p;while(q != NULL){p = q;q = q->next;delete p;}}delete [] htList;}int hash(const int &key) const{return abs(key%bucket);   //留余数法}linkedNode* find(const int &x) const{int i = hash(x);linkedNode *p = htList[i].head->next, *q = htList[i].head;while(p && p->data.first != x){q = p;p = p->next;}return q;   //返回找到元素的前一个节点,或者没有找到,返回最后一个元素}linkedNode* insert(const int &x){int i = hash(x);linkedNode *p = htList[i].head, *q = p;while(q != NULL){p = q;q = q->next;if(q && q->data.first == x){q->data.second++;return q;}}p->next = new linkedNode();p->next->data.first = x;p->next->data.second++;return p->next;}
};
int a[4001], b[4001], c[4001], d[4001];
int ab[4000*4000+1], cd[4000*4000+1];   //存储a+b,c+d
int main()
{linkedHash ht(16000057);int line, k=0;cin >> line;for(int i = 0; i < line; ++i){cin >> a[i] >> b[i] >> c[i] >> d[i];}for(int i = 0; i < line; ++i){for(int j = 0; j < line; ++j){ab[k] = a[i]+b[j];ht.insert(ab[k]);cd[k++] = -(c[i]+d[j]);}}int result = 0;linkedNode* p;for(int i = 0; i < k; ++i){p = ht.find(cd[i])->next;if(p && p->data.first == cd[i])result += p->data.second;}cout << result << endl;return 0;
}

2.4 偷懒失败,hash_map在poj中不存在

/*** @description: 4个数和为0的方案数,哈希法* @author: michael ming* @date: 2019/5/9 22:30* @modified by: */
#include <iostream>
#include <hash_map>
//#include <unordered_map>
using namespace std;
int a[4001], b[4001], c[4001], d[4001];
int ab[4000*4000+1], cd[4000*4000+1];   //存储a+b,c+d
int main()
{__gnu_cxx::hash_map<int, int> ht;
//    std::unordered_map<int, int> ht;int line, k=0;cin >> line;for(int i = 0; i < line; ++i){cin >> a[i] >> b[i] >> c[i] >> d[i];}for(int i = 0; i < line; ++i){for(int j = 0; j < line; ++j){ab[k] = a[i]+b[j];ht[ab[k]]++;cd[k++] = -(c[i]+d[j]);}}int result = 0;for(int i = 0; i < k; ++i){result += ht[cd[i]];}cout << result << endl;return 0;
}

2.5 哈希表+二叉查找树(超时)

可能是建立二叉树插入节点new太耗时了。

/*** @description: 4个数和为0的方案数,哈希法* @author: michael ming* @date: 2019/5/9 22:30* @modified by:*/
#include <iostream>
#include <math.h>
using namespace std;
class BSTNode
{public:int data, count;BSTNode *left, *right;BSTNode():count(1), left(NULL), right(NULL){}BSTNode(const int& d, BSTNode *l = NULL, BSTNode *r = NULL){data = d;   count = 1;   left = l;   right = r;}
};
class BST
{private:BSTNode* root;int nodeLen;
public:BST():root(NULL){}~BST(){}void clear(BSTNode* nodeP){if(nodeP == NULL)return;clear(nodeP->left);clear(nodeP->right);delete nodeP;}BSTNode* get_root() const {  return root;    }bool isEmpty() const {  return root == NULL;    }BSTNode* search(const int& d) const{BSTNode* p = search(d, root);return p;}BSTNode* search(const int d, BSTNode* p) const{while(p != NULL){if(d == p->data)return p;else if(d < p->data)p = p->left;elsep = p->right;}return NULL;}void insert(const int d){BSTNode *p = root, *prev = NULL;while(p != NULL){prev = p;if(d < p->data)p = p->left;elsep = p->right;}if(root == NULL)root = new BSTNode(d);else if(d < prev->data)prev->left = new BSTNode(d);elseprev->right = new BSTNode(d);}
};class linkedHash
{private:BST* ht_bstree; //散列表二叉树数组int bucket;  //散列表桶个数
public:linkedHash(int m):bucket(m){ht_bstree = new BST [bucket] ();}~linkedHash(){for(int i = 0; i < bucket; ++i){ht_bstree[i].clear(ht_bstree[i].get_root());}delete [] ht_bstree;}int hash(const int &key) const{return abs((((key+1000000000)%bucket)+1357)%bucket);   //留余数法}int find(const int &x) const{int i = hash(x);BSTNode *p = ht_bstree[i].search(x);if(p)return p->count;return 0;}void insert(const int x){int i = hash(x);BSTNode *p = ht_bstree[i].search(x);if(p)p->count++;elseht_bstree[i].insert(x);}
};
int a[4001], b[4001], c[4001], d[4001];
int ab[4000*4000+1], cd[4000*4000+1];   //存储a+b,c+d
int main()
{linkedHash ht(5000);    //多次调整括号内数值,超时或者内存超限int line, k=0;cin >> line;for(int i = 0; i < line; ++i){cin >> a[i] >> b[i] >> c[i] >> d[i];}for(int i = 0; i < line; ++i){for(int j = 0; j < line; ++j){ab[k] = a[i]+b[j];ht.insert(ab[k]);cd[k++] = -(c[i]+d[j]);}}int result = 0;for(int i = 0; i < k; ++i){result += ht.find(cd[i]);}cout << result << endl;return 0;
}

2.6 AC代码(哈希+数组法)

/*** @description: poj 2785 哈希法,数组实现* @author: michael ming* @date: 2019/5/20 18:17* @modified by: */
#include <iostream>
using namespace std;
int a[4001], b[4001], c[4001], d[4001];
const int hashtablesize = 20000001;//保证一定的富裕,装载因子0.75左右
int hasht[hashtablesize];
int count[hashtablesize];
int offset = 1000000000; // 该数 > 2^29(加上他后,就没有负数了,求模后比较方便使用下标值)
int hashfunc(int value)
{return value%hashtablesize;
}
int hashfunc_other(int value)
{return (value+3)%hashtablesize;
}
void insert(int num)
{int num_init = num;num = hashfunc(num+offset);while(hasht[num] != offset && hasht[num] != num_init)//解决冲突,不等于初始值(够不着的大数)(值改了,位子被占了),且不等于映射的值(冲突了),第一次进入循环,第一个条件肯定不满足。{num = hashfunc_other(num);//冲突了,继续寻找别的下标(换一个函数,不然相同的模在这可能无限循环)}hasht[num] = num_init;count[num]++;
}
int find(int num)
{int num_init = num;num = hashfunc(num+offset);while(hasht[num] != offset && hasht[num] != num_init)num = hashfunc_other(num);    //往下查找空位或者相等的值得位子if(hasht[num] == offset)    //找到的是空位子,则没有匹配的和等于0return 0;else    //找到了值相等的位子,把其对应的count位子里的个数返回return count[num];
}
int main()
{int line, k=0, value, i, j;cin >> line;for(i = 0; i < line; ++i){cin >> a[i] >> b[i] >> c[i] >> d[i];}for(i = 0; i < hashtablesize; ++i)hasht[i] = offset;  //hash表每个元素初始化为offsetfor(i = 0; i < line; ++i){for(j = 0; j < line; ++j){value = a[i]+b[j];insert(value);}}int result = 0;for(i = 0; i < line; ++i){for(j = 0; j < line; ++j){value = (-c[i]-d[j]);result += find(value);}}cout << result << endl;return 0;
}

POJ 2785 有多少种4个数相加等于0的方案(二分查找 or hash)相关推荐

  1. 51Nod-1090 3个数和为0【排序+二分查找】

    1090 3个数和为0 基准时间限制:1秒 空间限制:131072KB 分值:5难度:1级算法题 给出一个长度为N的无序数组,数组中的元素为整数,有正有负包括0,并互不相等.从中找出所有和 = 0的3 ...

  2. 数组两个整数相加 c语言,作业帮:给定一个整数数组,找出其中两个数相加等于目标值(去重set)...

    题目描述 给定一个整数数组,找出其中两个数相加等于目标值 输入 [1,3,5,7,9,11] 10 输出 1,9 3,7 代码: import java.util.HashMap; import ja ...

  3. 作业帮:给定一个整数数组,找出其中两个数相加等于目标值(去重set)

    题目描述 给定一个整数数组,找出其中两个数相加等于目标值输入 [1,3,5,7,9,11] 10输出 1,9 3,7 代码: import java.util.HashMap; import java ...

  4. excel几个数相加等于某个数_[求助]如何能计算出几个数字相加等于一个给定的数...

    QUOTE: 以下是引用jiang041111在2007-2-6 19:54:13的发言: 已知一个数字和一组数字,比如说2.6.78.90.34.21.35--,113,如何能自动找出哪几个数字相加 ...

  5. 数组-leetcode#15-找出三个数之和等于0的所有不重复序列

    class Solution { public:vector<vector<int>> threeSum(vector<int>& nums) {vecto ...

  6. excel几个数相加等于某个数_随机数加起来等于某个特定数的EXCEL实现方式

    问题:简单粗暴方式:用VBA循环: 有算法的VBA. 用EXCEL公式. 这里分享第三个思路, 用EXCEL公式来解决. EH灰袍法师提供了很巧妙的思路: 10个1-20的数, 要加起来等于100,那 ...

  7. leetcode 1: 找出两个数相加等于给定数 two sum

    问题描述 对于一个给定的数组,找出2个数,它们满足2个数的和等于一个特定的数,返回这两个数的索引.(从1开始) Given an array of integers, find two numbers ...

  8. 【POJ - 2785】4 Values whose Sum is 0 (二分,折半枚举)

    题干: The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, com ...

  9. 一个数里有那些约数用c++怎么做_如何从一堆数里找出哪几个数相加等于你要的值?...

    凑数在更深一步财务数据分析和核算中有着很重要的作用 你是否有遇到过收到的一笔款对应哪几个发票金额?一张发票对应哪几笔收款?等等其他方面需要从一堆数里凑几个数等于你要的值. 对于数字敏感的人,一些简单的 ...

最新文章

  1. 倍福ads通讯软件_软件定义汽车“性感”吗?东软睿驰有自己的答案
  2. php yield 导出文件,PHP yield 读取大文件
  3. leetcode算法题--Russian Doll Envelopes
  4. boost::planar_face_traversal用法的测试程序
  5. MySQL搭建主从复制 读写分离 分库分表 MyCat高可用
  6. Git 内部原理图解——对象、分支以及如何从零开始建仓库
  7. 怎么快速了解自己的MySQL服务器?
  8. 服务器php只显示文本,服务器上的php echos文件是文本而不是二进制文件
  9. linux装redis环境变量,linux 怎样安装redis
  10. python计算机中丢失api-ms-win-crt-runtime-l_api-ms-win-crt-runtime-l1-1-0.dll
  11. numpy教程:基本输入输出和文件输入输出Input and output
  12. PCL Save VTK File With Texture Coordinates 使用PCL库来保存带纹理坐标的VTK文件
  13. 西北工业大学noj数据结构实验003稀疏矩阵转置
  14. 论文查重 降重复度?
  15. Vulntarget靶场渗透笔记[持续更新中]
  16. 为什么爱奇艺会显示联通免流量服务器,联通爱奇艺流量定向包是怎么回事啊,是不是开通之后,这一个月里面看视讯免流量的...
  17. 降噪蓝牙耳机哪个品牌好?降噪蓝牙耳机排行推荐
  18. Excel IF 函数怎么用
  19. 服务器常见错误原因以及处理方式
  20. 设备管理器上不显示集成显卡(核显)问题解决

热门文章

  1. html间数据传送,Express框架与html之间如何进行数据传递(示例代码)
  2. 计算abc=a!+b!+c!
  3. 字体文件解析 c语言,如何正确地从C语言的文件中读取某些字符串?
  4. 8.在idea中配置maven
  5. Java微信公众平台获取签名
  6. iOS之加密的三种方法
  7. BZOJ4068 : [Ctsc2015]app
  8. 使用croc命令在Linux系统电脑之间传输文件和文件夹
  9. 重庆大二学生花了6年写出了操作系统
  10. 尘埃落定,初心未改——一个大学生的电子大赛感悟