这次趁热打铁找一个二分查找法的题目来解决一下:
题目描述:
Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2.
Note:
- Your returned answers (both index1 and index2) are not zero-based.
- You may assume that each input would have exactly one solution and you may not use the sameelement twice.
Example:
Input: numbers = [2,7,11,15], target = 9 Output: [1,2] Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2.
题目比较简单,就是找出2个数组元素之和为给出的target的索引(indices) ,要求索引不是从0开始的,从1开始。并且肯定有解,两个元素不相同。
方法1:
先暴力求解一下,这里也写出一个问题,判断的时候因为末尾没有return res 提示
warning: control reaches end of non-void function
原因是没有检测到return返回值,可能强制要求必须在末尾加上一个返回值,加上res即可,但是还是感到很奇怪,难道中间的返回值不能实现立即返回吗?暂时留下一个疑问,难道要执行完全部的循环才可以吗?总之这个方法的效率极低,打败10%左右的解法
另外vector 的初始化可以用vector<int> res(2)声明了两个元素的容器,并且默认值均为0 :
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
vector<int> res(2,2);
for(int i = 0; i < numbers.size()-1; i++)
{
for(int j = i + 1; j <= numbers.size()-1; j++)
{
if(numbers[i] + numbers[j] == target)
{
res[0] = i + 1;
res[1] = j + 1;
return res;
}
}
}
return res;
}
};
方法2:
现在尝试一下二分法解决问题:
当我用了二分查找法就相当的快速了,速度超过了 99% 的程序,但是因为所给的程序虽然有序,满足二分查找的条件,但是允许有重复值的存在,在上一篇我们提到了二分查找涉及到重复值时,单用上篇我们给出的算法就会出现些问题,为此,考虑这样:
即从迭代到的 索引为 i 后的进行二分查找,因为i前的必然不再搜索范围内,它们已经完成了搜索没有找到,这样既缩短了二分查找的时间,又解决了有与 numbers[i] 相同值的问题即 i < j 的条件,因为解法题目说明只有1种解法,如果结果是两个相同的数之和为目标,那么 i 后只可能有一个与 numbers[i] 相同的数,取其索引即可,故问题得到解决,代码为:
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
vector<int> res(2);
int i,j;
for(i = 0; i < numbers.size() - 1; i++)
{
j = binary_search(numbers,i,target - numbers[i]);
if(j != -1)
break;
}
res[0] = i + 1;
res[1] = j + 1;
return res;
}
int binary_search(vector<int>& numbers, int i, int t)
{
int low = i + 1;
int high = numbers.size()-1;
while(low <= high)
{
int mid = (low + high) / 2;
if(numbers[mid] == t)
return mid;
else if(numbers[mid] > t)
high = mid - 1;
else if(numbers[mid] < t)
low = mid + 1;
else;
}
return -1;
}
};