记录力扣刷题第二题
本文中包含C++两种方法的题解以及Java和Python的题解
题目描述如下
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
来源:LeetCode
思路:
看到这题写的是有序的数组,马上就想到了二分查找的算法,但由于昨天写的题运用了哈希表来降低查找操作的时间复杂度,并且运用哈希表写出来的代码也更简单,所以我先试了试哈希表,代码如下。
class Solution {
public:
int search(vector<int>& nums, int target) {
std::unordered_map<int, int> Hashtb;
for(int i = 0; i < nums.size(); ++i) {
Hashtb[nums[i]] = i;
auto it = Hashtb.find(target);
if(it != Hashtb.end()) {
return it->second;
}
}
return -1;
}
};
注意这里要先把数据放入哈希表再进行判断哈,不然数组中只有单个数据时会出错。运用哈希表的时间复杂度为O(n)。不过看执行结果:
执行用时:56 ms, 在所有 C++ 提交中击败了7.99%的用户
还是挺拉的,因此还是用二分查找的方法去写吧。二分查找的时间复杂度为 O ( l o g 2 n ) O(log~{2}n) O(log 2n),即以二为底n的对数,这里不展开证明,引用其他人的证明过程。显然,二分查找的时间复杂度比哈希表的方法低。试着写了写二分查找,也通过了,代码如下。
class Solution {
public:
int search(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1, mid = 0;
while(l <= r) {
mid = l + ((r - l)/2);
if(nums[mid] > target) {
r = mid - 1;
}
else if(nums[mid] < target) {
l = mid + 1;
}
else {//nums[mid] == target,找到目标了
return mid;
}
return -1;
}
};
要注意的是while里是l<=r,这里假设的是左闭右闭区间才能这么写,假如有一边是开区间,就要改变写法(也包括下面的mid是否加减1)。这里不再赘述,请读者自行思考。
Java和Python的思路与C++一致,代码如下
Java
class Solution {
public int search(int[] nums, int target) {
//这里使用左闭右开区间,即[l, r)
int l = 0, r = nums.length, mid = 0;
while(l < r) {
mid = l + ((r - l)/2);
if(nums[mid] > target) {
r = mid;//由于是开区间,这里没有减一
}
else if(nums[mid] < target) {
l = mid + 1;
}
else {
return mid;
}
return -1;
}
}
Python
class Solution:
def search(self, nums: List[int], target: int) -> int:
l, r = 0, len(nums) - 1
while l <= r:
mid = l + (r - l)//2
gt = nums[mid]
if gt > target:
r = mid - 1
elif gt < target:
l = mid + 1
else:
return mid
return -1