问题描述: 对应函数 find_two
快速找出数组中的两个数字,让这两个数字之和等于给定的数字。
想法: 如果把任意两个数字组合进行尝试的话,运算量是N*N不适合。 先将数组进行排序,然后从两头分别取数字进行组合,如果和大于目标数字则在大数字侧找下一个稍小一点的数字。 如果和小于目标数字则在小数字侧找下一个稍大一点的数字
扩展问题 1: 对应函数 find_three 快速找出数组中的三个数字,让这两个数字之和等于给定的数字。
扩展问题 2: 对应函数 find_three_near 快速找出数组中的三个数字,让这两个数字之和等于给定的数字或找到最接近的解。
想法: 想法与找两个数字类似,先找到一大一小的两个终点,然后用游标在这两个终点间进行遍历,寻找第三个数,使他们的和接近或等于目标数字。
#include <iostream>
#include <vector>
using namespace std;
void swap(int &a, int &b)
{
int tmp = 0;
tmp = a;
a = b;
b = tmp;
}
void quick_sort(int* parr, int lpos, int rpos)
{
int mid_pos = (lpos + rpos)/2;
int mid_val = parr[mid_pos];
int i = lpos, j = rpos;
if (lpos >= rpos)
return;
while (i < j)
{
if ((parr[i] < mid_val) && (i < j))
{
i++;
}
if ((parr[j] > mid_val) && (i < j))
{
j--;
}
if (i < j)
{
swap(parr[i], parr[j]);
}
}
mid_pos = j;
quick_sort(parr, lpos, mid_pos);
quick_sort(parr, mid_pos+1, rpos);
}
bool find_two(int arr[], int len, int num)
{
int i = 0, j = len-1;
bool result = false;
quick_sort(arr, 0, len-1);
while ((!result) && (i < j))
{
if ((arr[i] + arr[j]) == num)
result = true;
else if ((arr[i] + arr[j]) < num)
i++;
else
j--;
}
if (result)
cout << num << " = " << arr[i] << " + " << arr[j] << endl;
else
cout << "None" << endl;
return result;
}
bool find_three(int arr[], int len, int num)
{
int i = 0, j = len-1;
bool bfound = false;
int sum = 0, curr = 0;
vector<int> list;
if (len < 2)
return false;
quick_sort(arr, 0, len-1);
// not found
if ((arr[j-2] + arr[j-1] + arr[j] < num) || (arr[0] + arr[1] > num))
return false;
while ((j >= 0) && (arr[j] >= num))
j--;
if (j < 2)
return false;
while ((!bfound) && (i < j))
{
for (i = 0; i < j; i++)
{
sum = arr[i] + arr[j];
curr = i + 1;
while ((sum + arr[curr] < num) && (curr < j))
curr++;
if (sum + arr[curr] == num)
{
bfound = true;
list.push_back(i);
list.push_back(curr);
list.push_back(j);
break;
}
}
j--;
}
if (bfound)
{
cout << num << " = " << arr[list[0]];
for (i = 1; (size_t)i < list.size(); i++)
{
cout << " + " << arr[list[i]];
}
cout << endl;
}
else
cout << "None" << endl;
return bfound;
}
bool find_three_near(int arr[], int len, int num)
{
int i = 0, j = len-1;
bool bfound = false;
int sum = 0, curr = 0, min = num;
vector<int> list;
if (len < 2)
return false;
quick_sort(arr, 0, len-1);
// not found
if ((arr[j-2] + arr[j-1] + arr[j] < num) || (arr[0] + arr[1] > num))
return false;
while ((j >= 0) && (arr[j] >= num))
j--;
if (j < 2)
return false;
while ((!bfound) && (j > 1))
{
for (i = 0; i < j; i++)
{
sum = arr[i] + arr[j];
curr = i + 1;
while ((sum + arr[curr] < num) && (curr < j))
curr++;
if (sum + arr[curr] == num)
{
bfound = true;
list.clear();
list.push_back(i);
list.push_back(curr);
list.push_back(j);
break;
}
else if (min > abs((sum + arr[curr] - num)))
{
min = abs(sum + arr[curr] - num);
list.clear();
list.push_back(i);
list.push_back(curr);
list.push_back(j);
}
}
j--;
}
if (!bfound)
cout << "Not Found near value=" << min <<endl;
cout << num << " = " << arr[list[0]];
for (i = 1; (size_t)i < list.size(); i++)
{
cout << " + " << arr[list[i]];
}
cout << endl;
return bfound;
}
void main()
{
bool result = true;
int test[] = {5, 12, 11, 6, 9, 21, 30}; int num = 50; int limit = 3;
int len = sizeof(test)/sizeof(test[0]);
//int test[] = {5, 12, 11, 6, 9, 21, 30}; int num = 34;
//int len = sizeof(test)/sizeof(test[0]);
int test_near[] = {5, 12, 11, 6, 9, 21, 30}; int num_near = 52;
int len_near = sizeof(test_near)/sizeof(test_near[0]);
//find_two(test, len, num);
//result = find_three(test, len, num);
//if (!result)
// cout << "None" << endl;
find_three_near(test_near, len_near, num_near);
cin >> len;
}