对于给定的整数集合S,求出最大的d,使得a+b+c=d。
2017-01-13 23:21
411 查看
对于给定的整数集合S,求出最大的d,使得a+b+c=d。a,b,c,d互不相同,且都属于S。集合的元素个数小于等于2000个,元素的取值范围在[-2^28,2^28 - 1],假定可用内存空间为100MB,硬盘使用空间无限大,试分析时间和空间复杂度,找出最快的解决方法。
提示:两两相加转为多项式乘法,比如(1 2 4 6) + (2 3 4 5) => (x + x^2 + x^4 + x^6)*(x^2 + x^3 + x^4 + x^5) 。
#include <iostream>
#include<map>
#include "bitmap.h"
using namespace std;
#define M (1024*1024*512)
#define N 2000
multimap<int, int> mmp;
void printBitmap(int n) {
for (int i = 0; i < n; ++i) {
if (test(i)) {
cout << i << ' ';
}
}
cout << endl;
}
void printMutimap() {
multimap<int, int>::iterator i, iend;
iend = mmp.end();
for (i = mmp.begin(); i != iend; i++) {
cout << (*i).first << ' ' << (*i).second << endl;
}
}
int* initRandom(int len, int range) {
int* randoms = new int[len];
srand(unsigned(time(0)));
for (int i = 0; i < len; i++) {
randoms[i] = rand() % range;
}
return randoms;
}
void printArray(int* arr, int len) {
cout << "数组:" << endl;
for (int i = 0; i < len; ++i) {
cout << arr[i] << ' ';
}
cout << endl;
}
/*求出集合中每2个数的和,并用bitmap存储,
* multimap里边的key为2个数的和,value值为较小的数,则另一个值为key-value*/
void enumSum(int*arr, int len) {
for (int i = 1; i < len; ++i) {
if (arr[i - 1] != arr[i])
for (int j = i; j < len; ++j) {
//arr[i - 1] != arr[j]和的2个数必须不同
if (arr[j - 1] != arr[j] && arr[i - 1] != arr[j]) {
int sum = arr[i - 1] + arr[j];
// set(sum);
mmp.insert(make_pair(sum, arr[i - 1]));
}
}
}
}
int* enumSub(int* arr, int len) {
typedef multimap<int, int>::size_type sz_type;
for (int i = len - 1; i >= 0; --i) {
for (int j = i - 1; j >= 0; --j) {
if (arr[i] != arr[j]) {
int sub = arr[i] - arr[j];
// if (test(sub)) {
sz_type entries = mmp.count(sub);
if (entries == 0) {
continue;
} else {
multimap<int, int>::iterator iter = mmp.find(sub);
for (sz_type cnt = 0; cnt != entries; ++cnt, ++iter) {
if (iter->second == arr[i]
|| iter->second == arr[j]) {
continue;
} else if (iter->first - iter->second == arr[i]
|| iter->first - iter->second == arr[j]) {
continue;
}
/*M区间[-2^28,2^28 - 1],所以正式结果必须减去(2^28-1)*/
int* result = new int[4];
result[0] = iter->first - iter->second;
result[1] = iter->second;
result[2] = arr[j];
result[3] = arr[i];
return result;
}
}
// }
}
}
}
return NULL;
}
int main() {
bitmap = new int[M / 32]; //M / 32
memset(bitmap, 0, M / 32 * sizeof(int)); //M * sizeof(int)
int* arr = initRandom(N, M);
sort(arr, arr + N);
// printArray(arr, N);
clock_t start_time = clock();
enumSum(arr, N);
/*printBitmap(N);
printMutimap();
*/
// enumSub(arr, N);
int* result = enumSub(arr, N);
if (result) {
cout << result[0] << '+' << result[1] << '+' << result[2] << '='
<< result[3] << endl;
}
clock_t end_time = clock();
cout << "Running time is: "
<< static_cast<double>(end_time - start_time) / CLOCKS_PER_SEC
* 1000 << "ms" << endl; //输出运行时间
return 0;
}
提示:两两相加转为多项式乘法,比如(1 2 4 6) + (2 3 4 5) => (x + x^2 + x^4 + x^6)*(x^2 + x^3 + x^4 + x^5) 。
#include <iostream>
#include<map>
#include "bitmap.h"
using namespace std;
#define M (1024*1024*512)
#define N 2000
multimap<int, int> mmp;
void printBitmap(int n) {
for (int i = 0; i < n; ++i) {
if (test(i)) {
cout << i << ' ';
}
}
cout << endl;
}
void printMutimap() {
multimap<int, int>::iterator i, iend;
iend = mmp.end();
for (i = mmp.begin(); i != iend; i++) {
cout << (*i).first << ' ' << (*i).second << endl;
}
}
int* initRandom(int len, int range) {
int* randoms = new int[len];
srand(unsigned(time(0)));
for (int i = 0; i < len; i++) {
randoms[i] = rand() % range;
}
return randoms;
}
void printArray(int* arr, int len) {
cout << "数组:" << endl;
for (int i = 0; i < len; ++i) {
cout << arr[i] << ' ';
}
cout << endl;
}
/*求出集合中每2个数的和,并用bitmap存储,
* multimap里边的key为2个数的和,value值为较小的数,则另一个值为key-value*/
void enumSum(int*arr, int len) {
for (int i = 1; i < len; ++i) {
if (arr[i - 1] != arr[i])
for (int j = i; j < len; ++j) {
//arr[i - 1] != arr[j]和的2个数必须不同
if (arr[j - 1] != arr[j] && arr[i - 1] != arr[j]) {
int sum = arr[i - 1] + arr[j];
// set(sum);
mmp.insert(make_pair(sum, arr[i - 1]));
}
}
}
}
int* enumSub(int* arr, int len) {
typedef multimap<int, int>::size_type sz_type;
for (int i = len - 1; i >= 0; --i) {
for (int j = i - 1; j >= 0; --j) {
if (arr[i] != arr[j]) {
int sub = arr[i] - arr[j];
// if (test(sub)) {
sz_type entries = mmp.count(sub);
if (entries == 0) {
continue;
} else {
multimap<int, int>::iterator iter = mmp.find(sub);
for (sz_type cnt = 0; cnt != entries; ++cnt, ++iter) {
if (iter->second == arr[i]
|| iter->second == arr[j]) {
continue;
} else if (iter->first - iter->second == arr[i]
|| iter->first - iter->second == arr[j]) {
continue;
}
/*M区间[-2^28,2^28 - 1],所以正式结果必须减去(2^28-1)*/
int* result = new int[4];
result[0] = iter->first - iter->second;
result[1] = iter->second;
result[2] = arr[j];
result[3] = arr[i];
return result;
}
}
// }
}
}
}
return NULL;
}
int main() {
bitmap = new int[M / 32]; //M / 32
memset(bitmap, 0, M / 32 * sizeof(int)); //M * sizeof(int)
int* arr = initRandom(N, M);
sort(arr, arr + N);
// printArray(arr, N);
clock_t start_time = clock();
enumSum(arr, N);
/*printBitmap(N);
printMutimap();
*/
// enumSub(arr, N);
int* result = enumSub(arr, N);
if (result) {
cout << result[0] << '+' << result[1] << '+' << result[2] << '='
<< result[3] << endl;
}
clock_t end_time = clock();
cout << "Running time is: "
<< static_cast<double>(end_time - start_time) / CLOCKS_PER_SEC
* 1000 << "ms" << endl; //输出运行时间
return 0;
}
相关文章推荐
- 对于给定的整数集合S,求出最大的d,使得a+b+c=d。
- 堆的数据结构能够使得堆顶总是维持最大(对于大根堆)或最小(对于小根堆),给定一个数组,对这个数组进行建堆,则平均复杂度是多少?如果只是用堆的 push 操作,则一个大根堆依次输入 3,7,2,4,1,5,8 后,得到的堆的结构示意图是下述图表中的哪个?
- 一道题:给定一整数序列A1,A2,...,An(可能有负数),求A1到An的一个自序列,使得Ai到Aj的和最大。例如:整数序列-2,11,-4,13,-5,2,-5,-3,12,-9的最大子序列为21
- 对于1个正整数N,将其拆分成几个正整数的和,如何拆分可使得其乘积最大?
- 有一个直方图,用一个整数数组表示,其中每列的宽度为1,求所给直方图包含的最大矩形面积。比如,对于直方图[2,7,9,4],它所包含的最大矩形的面积为14(即[7,9]包涵的7x2的矩形)。给定一个直方图A及它的总宽度n,请返回最大矩形面积。保证直方图宽度小于等于500。保证结果在int范围内。
- 给定一个由整数组成二维矩阵(r*c),现在需要找出它的一个子矩阵,使得这个子矩阵内的所有元素之和最大,并把这个子矩阵称为最大子矩阵。
- 给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数
- 整数分解使得积最大
- 网易面试题之小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题: 定义函数f(x)为x最大的奇数约数,x为正整数。 例如:f(44) = 11. 现在给出一个N,需要求
- 判断集合中是否有两个数的和等于某个给定整数
- 数论 - 整除问题 --- 整数集合中找出3的最大倍数
- 最大子序列问题:给定一整数序列A1,A2,A3...An(可能有负数),求A1~An的一个最大子序列Ai~Aj的和。
- 百度笔试:给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。 要求:空间复杂度O(1),时间复杂度为O(n)
- 网易面试题之小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题: 定义函数f(x)为x最大的奇数约数,x为正整数。 例如:f(44) = 11. 现在给出一个N,需要求
- 给定一个整数数组(有正数有负数),找出总和最大的连续数列,并返回总和。
- 给定一个整数数组,通过变换使得数组的左边为奇右边为偶数!
- 对于一个有序数组,我们通常采用二分查找的方式来定位某一元素,请编写二分查找的算法,在数组中查找指定元素。 给定一个整数数组A及它的大小n,同时给定要查找的元素val,请返回它在数组中的位置(从0开始),若不存在该元素,返回-1。若该元素出现多次,请返回第一次出现的位置。
- 346/5000 给定一个n个整数的数组S,在S中找到三个整数,使得总和最接近给定数量的目标。 返回三个整数的和。
- 网易面试题之小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题: 定义函数f(x)为x最大的奇数约数,x为正整数。 例如:f(44) = 11. 现在给出一个N,需要求
- 数据结构与算法——给定整数A1,A2,....An,....(可能有负数),求该数据序列的最大子序列的和