题目描述
- 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
算法分析
- 数列满足递增,设两个头尾两个指针i和j,
-
若ai + aj == sum,就是答案(相差越远乘积越小)
-
若ai + aj > sum,aj肯定不是答案之一(前面已得出 i 前面的数已是不可能),j -= 1
-
若ai + aj < sum,ai肯定不是答案之一(前面已得出 j 后面的数已是不可能),i += 1
提交代码:
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> array, int sum) {
if (array.empty())
return vector<int>();
vector<int> result;
auto i = array.cbegin();
auto j = array.cend() - 1;
while (i < j)
{
if ((*i + *j) > sum)
--j;
else if ((*i + *j) < sum)
++i;
else
{
result.push_back(*i);
result.push_back(*j);
break;
}
}
return result;
}
};
测试代码:
// ====================测试代码====================
void Test(const char* testName, vector<int> data, int sum, vector<int> expected)
{
if (testName != nullptr)
printf("%s begins: ", testName);
Solution s;
vector<int> result = s.FindNumbersWithSum(data, sum);
if (result == expected)
{
printf("Passed. \n");
}
else
printf("FAILED. \n");
}
// 存在和为s的两个数字,这两个数字位于数组的中间
void Test1()
{
vector<int> data = { 1, 2, 4, 7, 11, 15 };
Test("Test1", data, 15, vector<int>{4, 11});
}
// 存在和为s的两个数字,这两个数字位于数组的两段
void Test2()
{
vector<int> data = { 1, 2, 4, 7, 11, 16 };
Test("Test2", data, 17, vector<int>{1, 16});
}
// 不存在和为s的两个数字
void Test3()
{
vector<int> data = { 1, 2, 4, 7, 11, 16 };
Test("Test3", data, 10, vector<int>());
}
// 鲁棒性测试
void Test4()
{
Test("Test4", vector<int>(), 0, vector<int>());
}
// 包含多个符合条件的情况
void Test5()
{
vector<int> data = { 0, 2, 4, 7, 11, 16 };
Test("Test5", data, 11, vector<int>{0, 11});
}
int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
return 0;
}