1[Leetcode 35]给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为
O(log n)的算法。示例 1:
输入: nums = [1,3,5,6], target = 5 输出: 2示例 2:
输入: nums = [1,3,5,6], target = 2 输出: 1示例 3:
输入: nums = [1,3,5,6], target = 7 输出: 4提示:
1 <= nums.length <= 104-104 <= nums[i] <= 104nums为 无重复元素 的 升序 排列数组-104 <= target <= 104
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int low=0,high=nums.size()-1,mid;
while(low<=high)
{
mid=low+(high-low)/2;
if(nums[mid]==target) return mid;
else if(nums[mid]<target) low=mid+1;
else high=mid-1;
}
return low;
}
};
分析:典型的二分搜索,不难发现规律,当搜索不到该元素时,low所在位置即元素应插入位置
时间复杂度:O(logn)
空间复杂度:O(1)
2.[leetcode 34]
给你一个按照非递减顺序排列的整数数组
nums,和一个目标值target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值
target,返回[-1, -1]。你必须设计并实现时间复杂度为
O(log n)的算法解决此问题。
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int first=searchFirst(nums,target); //左边界
int last=searchLast(nums,target); //右边界
vector<int> range{first,last};
return range;
}
private:
//寻找左边界
int searchFirst(vector<int>& nums, int target) {
int left=0;
int right=nums.size()-1;
while(left<=right)
{
int mid=left+(right-left)/2;
if(nums[mid]==target){
//如果前一个元素比目标值小则说明已找到左边界
if(mid==0||nums[mid-1]<nums[mid])
return mid;
//否则将区间往左边压缩继续搜索
right=mid-1;
}
else if(nums[mid]<target)
left=mid+1;
else right=mid-1;
}
return -1;//没搜到返回-1
}
//寻找右边界
int searchLast(vector<int>& nums, int target) {
int left=0;
int right=nums.size()-1;
while(left<=right)
{
int mid=left+(right-left)/2;
if(nums[mid]==target){
//如果后一个元素比目标值大则说明已找到右边界
if(mid==nums.size()-1||nums[mid+1]>nums[mid])
return mid;
//否则将区间往右边压缩继续搜索
left=mid+1;
}
else if(nums[mid]<target)
left=mid+1;
else right=mid-1;
}
return -1;//没搜到返回-1
}
};
分析:基于二分查找法进行修改,核心是弄清在搜索到匹配值时何时返回,何时继续压缩区间
时间复杂度:O(logn)
空间复杂度:O(1)
3.[leetcode 69]
给你一个非负整数
x,计算并返回x的 算术平方根 。由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意:不允许使用任何内置指数函数和算符,例如
pow(x, 0.5)或者x ** 0.5。
解法一:二分法
class Solution { public: int mySqrt(int x) { int l = 0, r = x, ans = -1; while (l <= r) { int mid = l + (r - l) / 2; if ((long long)mid * mid <= x) //long long 防溢出 { ans = mid; l = mid + 1; } else { r = mid - 1; } } return ans; } };
分析:这个二分查找法要搜索的对象是平方小于等于x的最大整数
时间复杂度:O(logx)
空间复杂度: O(1)
解法二:暴力匹配
class Solution {
public:
int mySqrt(int x) {
int i=1;
while((long long)i*i<=x) i++;
return i-1;
}
};
时间复杂度:O(根号n)
空间复杂度: O(1)
值得注意的是:根号n的时间复杂度高于logn的时间复杂度
解法三:e、ln计算器
class Solution { public: int mySqrt(int x) { int ans=1/2.0*exp(1/2.0*log(x)); return (ans+1)*(ans+1)<=x?ans+1:ans; } };
分析:由于计算精度问题,需检验ans和ans+1哪个是正确答案
时间复杂度:O(1)
空间复杂度:O(1)
4.[Leetcode 369]
给你一个正整数
num。如果num是一个完全平方数,则返回true,否则返回false。完全平方数 是一个可以写成某个整数的平方的整数。换句话说,它可以写成某个整数和自身的乘积。
不能使用任何内置的库函数,如
sqrt。
class Solution {
public:
bool isPerfectSquare(int num) {
int l = 0, r = num, ans = -1;
while (l <= r) {
int mid = l + (r - l) / 2;
if ((long long)mid * mid <= num) {//long long 防溢出 {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
if(ans*ans==num) return true;
return false;
}
};
分析:基于上一道题写难度就不大了 ,上面展示用二分法完成,当搜索到的ans正好是开根数,则说明num为完全平方数
时间复杂度:O(logn)
空间复杂度:O(1)
文章讲述了如何利用二分搜索算法在有序数组中高效地找到目标值的插入位置、查找范围以及判断一个数是否为完全平方数,所有解决方案的时间复杂度均为O(logn)。

1314

被折叠的 条评论
为什么被折叠?



