题目一:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得他们的和正好是s。
分析:这个问题首先能想到用穷举的方法穷举出所有2个数字的组合判断是否符合条件。有这个想法其实可以说出来,证明你反应快,maybe。 然后对于排序数组而言其实可以使用双指针的方法,一个低位一个高位,从指向第一个和最后一个数字开始,如果和小于s,低位指针++,如果和大于s,高位指针--,直到遍历完全。我个人觉得其实这道题目还隐含没有重复元素这一条件,因为说了递增
vector<vector<int> > FindTwoNums(vector<int> nums, int s)
{
vector<vector<int> > res;
if (nums.size() > 1 && s > 0) {
int low = 0;
int high = nums.size()-1;
while (low < high)
{
int sum = nums[low] + nums[high];
if (sum == s)
{
vector<int> temp = {nums[low], nums[high--]};
res.push_back(temp);
}
else if (sum < s)
{
++low;
}
else {
--high;
}
}
}
return res;
}
int main()
{
vector<int> nums = {1,2,3,4,11,14};
vector<vector<int> > res =
FindTwoNums(nums, 15);
if (!res.empty())
{
for (auto v : res)
{
for (auto num : v)
cout << num << " ";
cout << endl;
}
}
getchar();
return 0;
}
效果:
题目二:输入一个正数s, 打印出所有和为s的连续正数序列(至少含有两个数)。例如输入15,输出三个序列 1 2 3 4 5, 4 5 6 , 7 8;
分析:有了第一题的经验,其实可以找到思路,就是用高低两个指针来进行遍历,低指针的界限是(s+1)/ 2,这道题的高指针从指向2开始,低指针指向1,然后进行遍历。
//返回序列从low到hihg
vector<int> ContinuousSequence(int low, int high)
{
vector<int> res(high - low + 1);
for (int &num : res)
num = low++;
return res;
}
//获得和为s的连续序列
vector<vector<int> > FindContinuousSequence(int s)
{
vector<vector<int> > res;
if (s < 3) return res;
int low = 1;
int high = 2;
int curSum = low + high;
while (low < (s + 1) / 2)
{
if (curSum == s)
{
vector<int> temp = ContinuousSequence(low, high);
res.push_back(temp);
curSum -= low++;
}
else if (curSum < s)
{
++high;
curSum += high;
}
else {
curSum -= low++;
}
}
return res;
}
int main()
{
int s = 0;
while (cin >> s)
{
vector<vector<int> > res =
FindContinuousSequence(s);
if (!res.empty())
{
for (auto v : res)
{
for (int num : v)
cout << num << " ";
cout << endl;
}
cout << endl;
}
else
cout << "none" << endl;
}
return 0;
}
结果:
总结:注意本题中求low到high的和不要每次求一次,而是对curSum进行操作,及时更新,这样避免重复计算,提高效率。还有就是记住终止条件 low < ( s + 1)/ 2,因为序列最少两个数字。