大体框架如下:
完整写法如下:
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
while (left <= right) {
int middle = left + (right - left) / 2; // 避免整数溢出
if (nums[middle] > target) {
right = middle - 1;
}
else if (nums[middle] < target) {
left = middle + 1;
}
else {
return middle;
}
}
return -1;
}
};
int main() {
Solution solution;
vector<int> nums = { -1, 0, 3, 5, 9, 12 };
int target = 9;
int result = solution.search(nums, target);
if (result != -1) {
cout << "Element found at index: " << result << endl;
}
else {
cout << "Element not found in the array." << endl;
}
return 0;
}
运行结果:
难点理解:
1.
在 `Solution` 类的 `search` 方法中,当找到目标值 `target` 时,确实会返回一个 `middle` 值,这个 `middle` 是数组中目标值的索引。然而,在 `main` 函数中,我们使用了一个 `int result` 变量来接收 `search` 方法的返回值:
int result = solution.search(nums, target);
这里的 `result` 变量是用来存储 `search` 方法返回的索引值的。因此,当 `search` 方法找到了目标值并返回了对应的索引 `middle`,这个 `middle` 值就被赋给了 `result` 变量。
接下来,在 `if-else` 语句中,我们检查 `result` 变量的值:
if (result != -1) {
cout << "Element found at index: " << result << endl;
} else {
cout << "Element not found in the array." << endl;
}
如果 `result` 不等于 `-1`,这意味着 `search` 方法成功找到了目标值,并且 `result` 包含了目标值在数组 `nums` 中的索引。因此,我们打印出 "Element found at index: " 后面跟着 `result`,也就是目标值的索引。
如果 `result` 等于 `-1`,这意味着 `search` 方法没有找到目标值,因此我们打印出 "Element not found in the array."。
总结来说,`result` 变量是 `main` 函数中的一个局部变量,它被用来暂存 `search` 方法的返回值,这个返回值可能是目标值的索引(在数组中找到时)或者 `-1`(在数组中未找到时)。
2.怎么理解下面这句代码?
int middle = left + (right - left) / 2; // 避免整数溢出
在二分查找算法中,计算中间索引 `middle` 是一个关键步骤。通常,中间索引可以通过 `(left + right) / 2` 来计算。然而,这种计算方式在某些情况下可能会导致整数溢出。
整数溢出是指当一个整数类型的变量存储的数值超过了该类型的可表示范围时发生的现象。在C++中,整数类型的变量(如 `int`)有一个最大值,如果计算结果超出了这个最大值,就会发生溢出,导致不可预测的结果。
考虑以下例子,假设 `left` 和 `right` 都是 `int` 类型,并且它们的最大值是 `INT_MAX`(在大多数系统上,`int` 类型的大小为32位,`INT_MAX` 大约为21亿):
int left = INT_MAX / 2;
int right = left + 1;
int middle = (left + right) / 2;
在这个例子中,`left + right` 的计算结果会超出 `int` 类型的最大值,因为 `INT_MAX / 2 + 1` 已经接近 `INT_MAX`,再除以2的结果将超出 `int` 的范围。
为了避免这种情况,我们可以使用 `left + (right - left) / 2` 来计算 `middle`,这样可以保证结果永远不会超过 `int` 的最大值。这是因为 `right - left` 的结果会小于 `int` 的最大值,所以加上 `left` 后仍然安全。
这种方法利用了等式:
left + (right - left) / 2 = (left + right) / 2
但是,它在计算时更加安全,因为它避免了将两个大数相加可能导致的整数溢出。