力扣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
题目分析
题目很好理解,在数组中寻找一个数,如果没有则返回插入位置
解题思路
利用二分的思想快速找到位置,因为数组严格递增,如果数组中间值大于目标值,那么右半边数组的所有数都大于目标值,可直接缩小搜索范围,同理左边,便能很快定位
代码实现
class Solution {
public:int searchInsert(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 right+1;}
};
力扣33搜索旋转排序数组
整数数组 nums 按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。
你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。
示例 1:
输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4
示例 2:
输入:nums = [4,5,6,7,0,1,2], target = 3
输出:-1
示例 3:
输入:nums = [1], target = 0
输出:-1
提示:
1 <= nums.length <= 5000
-104 <= nums[i] <= 104
nums 中的每个值都 独一无二
题目数据保证 nums 在预先未知的某个下标上进行了旋转
-104 <= target <= 104
题目分析
给定一个升序的数组和目标值,在数组经过向右旋转多次后,搜索目标值
解题思路
利用二分法,因为原来的数组是升序的,即使经过旋转后,数组仍然呈现两部分的严格递增,且前一部分的初始值一定大于另一部分的末尾值,这时我们可以分为两种情况:
1.首先将旋转后的数组第一个值与中间值比较,如果中间值大,那么旋转后的分割点(也就是原数组的nums[0])在中间值以后,那么我们可以保证中间值前面都是严格递增
然后再利用二分,当目标值小于中间值时,改变右边界,注意:改变的同时一定要保证目标值也小于旋转后的nums[0]因为它有可能在后半部分
2.当中间值小于数组第一个值时,分割点在中间值前面,同理可以保证中间值后面都是严格递增
代码实现
class Solution {
public:int search(vector<int>& nums, int target) {int n=nums.size();if(!n)return -1;if(n==1)return nums[0]==target?0:-1;int l=0,r=n-1;while(l<=r){int mid=(l+r)/2;if(nums[mid]==target)return mid;if(nums[0]<=nums[mid]){if(target<nums[mid]&&target>=nums[0]){r=mid-1;}else{l=mid+1;}}else{if(target>nums[mid]&&target<=nums[n-1]){l=mid+1;}else{r=mid-1;}}}return -1;}
};