力扣刷题记录二:704、二分查找

记录力扣刷题第二题

本文中包含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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值