题目
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例1
输入:
[1,3,5,6] , 5
输出:
2
示例2
输入:
[1,3,5,6] , 2
输出:
1
示例3
输入:
[1,3,5,6] , 7
输出:
4
示例4
输入:
[1,3,5,6] , 0
输出:
0
解法
参考网址
- 是二分查找问题,但是又有所不同
- 二分查找有两种模版
- 在循环体内查找目标元素,把区间分成三份
[mid] return
[left,mid-1] end = mid-1
[mid+1,right] left = mid+1
int searchInsert(vector<int>& nums, int target) {
int len = nums.size();
int left = 0;
int right = len - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
//int mid = (left + right) / 2; right和left很大时可能会溢出
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
- 在循环体内排除一定不存在目标答案的区间,把区间分成两份,考虑中间元素[mid]在什么情况下一定不是目标元素
- [left,mid] right = mid
[mid+1,right] left = mid+1
- [left,mid] right = mid
//(本题就是这个情况,target < nums[mid] 时一定不是解)
int searchInsert(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)
return mid;
else if(check(mid))
left = mid+1;
else
right = mid;
}
return left;
}
- [left,mid-1] right = mid-1
[mid,right] left = mid
有可能陷入死循环 只有看到 left = mid 的时候,才需要调整成为上取整,
nums[0]=0 nums[1]=5
left = 0 right = 1 mid = first+(end-first)/2 = 0 求
left = mid right不变 陷入死循环
解决方法 mid = first+(end-first+1)/2 = 1
int searchInsert(vector<int>& nums, int target) {
int left = 0;
int right = nums.size()-1;
while(left<right)
{
int mid = left+(right-left+1)/2;
if (nums[mid]==target)
return mid;
else if(check(mid))
left = mid;
else
right = mid-1;
}
return left;
}
- 这里要求的是大于等于 target 的第 1 个元素的位置。
代码
#include <stdio.h>
#include <vector>
#include <iostream>
using namespace std;
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int n = nums.size();
int left = 0;
int right = n - 1; // 定义target在左闭右闭的区间里,[left, right]
while (left <= right) { // 当left==right,区间[left, right]依然有效
int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
if (nums[middle] > target) {
right = middle - 1; // target 在左区间,所以[left, middle - 1]
} else if (nums[middle] < target) {
left = middle + 1; // target 在右区间,所以[middle + 1, right]
} else { // nums[middle] == target
return middle;
}
}
// 分别处理如下四种情况
// 目标值在数组所有元素之前 [0, -1]
// 目标值等于数组中某一个元素 return middle;
// 目标值插入数组中的位置 [left, right],return right + 1
// 目标值在数组所有元素之后的情况 [left, right], return right + 1
return right + 1;
}
};
/*
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int n = nums.size();
int left = 0;
int right = n; // 定义target在左闭右开的区间里,[left, right) target
while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间
int middle = left + ((right - left) >> 1);
if (nums[middle] > target) {
right = middle; // target 在左区间,在[left, middle)中
} else if (nums[middle] < target) {
left = middle + 1; // target 在右区间,在 [middle+1, right)中
} else { // nums[middle] == target
return middle; // 数组中找到目标值的情况,直接返回下标
}
}
// 分别处理如下四种情况
// 目标值在数组所有元素之前 [0,0)
// 目标值等于数组中某一个元素 return middle
// 目标值插入数组中的位置 [left, right) ,return right 即可
// 目标值在数组所有元素之后的情况 [left, right),return right 即可
return right;
}
};
*/
int main()
{
vector<int> v(4,0);
v[0]=1;v[1]=3;v[2]=5;v[3]=6;
vector<int> w(3,0);
w[0]=1;w[1]=3;w[2]=5;
vector<int> z(1,0);
z[0]=1;
Solution s;
cout<<s.searchInsert(v,2);
}
今天也是爱zz的一天哦!