278. 第一个错误的版本
难度简单259
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有
n
个版本[1, 2, ..., n]
,你想找出导致之后所有版本出错的第一个错误的版本。你可以通过调用
bool isBadVersion(version)
接口来判断版本号version
是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。示例:
给定 n = 5,并且 version = 4 是第一个错误的版本。 调用 isBadVersion(3) -> false 调用 isBadVersion(5) -> true 调用 isBadVersion(4) -> true 所以,4 是第一个错误的版本。
class Solution {
public:
int firstBadVersion(int n) {
if(isBadVersion(1)) return 1;
int left = 1;
int right =n;
while(right-left>1){
int mid = left+(right-left)/2;
if(isBadVersion(mid)){
right = mid;
}
else left = mid;
}
return right;
}
};
35. 搜索插入位置
难度简单837
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例 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
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
if(target<=nums[0])return 0;
if(target>nums[nums.size()-1]) return nums.size();
int left = 0;
int right = nums.size()-1;
while(right-left>1){
int mid = left + (right-left)/2;
if(nums[mid]>target) right = mid;
else left = mid;
}
if(nums[left]==target) return left;
else return right;
}
};
34. 在排序数组中查找元素的第一个和最后一个位置
难度中等655收藏分享切换为英文接收动态反馈
给定一个按照升序排列的整数数组
nums
,和一个目标值target
。找出给定目标值在数组中的开始位置和结束位置。你的算法时间复杂度必须是 O(log n) 级别。
如果数组中不存在目标值,返回
[-1, -1]
。示例 1:
输入: nums = [5,7,7,8,8,10], target = 8 输出: [3,4]
示例 2:
输入: nums = [5,7,7,8,8,10], target = 6 输出: [-1,-1]
int search(vector<int>& nums, int target) {
int i = 0;
int j = nums.size()-1;
while(i<=j){
int m = (i+j)/2;
if(nums[m]<=target) i = m+1;
else j = m-1;
}
int right = i;
i = 0;
j = nums.size()-1;
while(i<=j){
int m = (i+j)/2;
if(nums[m]<target) i = m+1;
else j = m-1;
}
int left = j;
return right-left-1;
}
33. 搜索旋转排序数组
难度中等1205
整数数组
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
。示例 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
-10^4 <= nums[i] <= 10^4
nums
中的每个值都 独一无二nums
肯定会在某个点上旋转-10^4 <= target <= 10^4
**进阶:**你可以设计一个时间复杂度为
O(log n)
的解决方案吗?
class Solution {
public:
int search(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;
if(nums[mid]<nums[left]) {//mid在右边
if(target<nums[left]){//target is on the right
if(nums[mid]>target) right = mid -1;
else left = mid +1;
}
else{//target is on the left
right = mid -1;
}
}
else{//mid在左边
if(target<nums[left]){//target is on the right
left = mid +1;
}
else{//target is on the left
if(nums[mid]>target) right = mid -1;
else left = mid +1;
}
}
}
return -1;
}
};
81. 搜索旋转排序数组 II
难度中等296
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组
[0,0,1,2,2,5,6]
可能变为[2,5,6,0,0,1,2]
)。编写一个函数来判断给定的目标值是否存在于数组中。若存在返回
true
,否则返回false
。示例 1:
输入: nums = [2,5,6,0,0,1,2], target = 0 输出: true
示例 2:
输入: nums = [2,5,6,0,0,1,2], target = 3 输出: false
进阶:
- 这是 搜索旋转排序数组 的延伸题目,本题中的
nums
可能包含重复元素。- 这会影响到程序的时间复杂度吗?会有怎样的影响,为什么?
class Solution {
public:
bool search(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 true;
if(nums[mid]==nums[left]) left++;
else if(nums[mid]<nums[left]){//mid is on the right
if(target<nums[left]){//target is on the right
if(nums[mid]>target) right = mid -1;
else left = mid +1;
}
else //target is on the left
right = mid -1;
}
else{//mid is on the left
if(target<nums[left]){//mid is on the right
left = mid +1;
}
else{
if(nums[mid]>target) right = mid -1;
else left = mid +1;
}
}
}
return false;
}
};
153. 寻找旋转排序数组中的最小值
难度中等363
假设按照升序排序的数组在预先未知的某个点上进行了旋转。例如,数组
[0,1,2,4,5,6,7]
可能变为[4,5,6,7,0,1,2]
。请找出其中最小的元素。
示例 1:
输入:nums = [3,4,5,1,2] 输出:1
示例 2:
输入:nums = [4,5,6,7,0,1,2] 输出:0
示例 3:
输入:nums = [1] 输出:1
提示:
1 <= nums.length <= 5000
-5000 <= nums[i] <= 5000
nums
中的所有整数都是 唯一 的nums
原来是一个升序排序的数组,但在预先未知的某个点上进行了旋转
class Solution {
public:
int findMin(vector<int>& nums) {
if(nums.size()==1)return nums[0];
int left =0;
int right = nums.size()-1;
while(right>left){
int mid = left + (right-left)/2;
if(nums[mid]<nums[right]){//mid is on the right
right = mid;
}
else
left = mid+1;
}
return nums[left];
}
};
154. 寻找旋转排序数组中的最小值 II
难度困难246
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组
[0,1,2,4,5,6,7]
可能变为[4,5,6,7,0,1,2]
)。请找出其中最小的元素。
注意数组中可能存在重复的元素。
示例 1:
输入: [1,3,5] 输出: 1
示例 2:
输入: [2,2,2,0,1] 输出: 0
说明:
- 这道题是 寻找旋转排序数组中的最小值 的延伸题目。
- 允许重复会影响算法的时间复杂度吗?会如何影响,为什么?
class Solution {
public:
int findMin(vector<int>& nums) {
if(nums.size()==1)return nums[0];
int left =0;
int right = nums.size()-1;
while(right>left){
int mid = left + (right-left)/2;
if(nums[mid]<nums[right]){//mid is on the right
right = mid;
}
else if(nums[mid]==nums[right]){
right--;
}
else
left = mid+1;
}
return nums[left];
}
};
162. 寻找峰值
难度中等386
峰值元素是指其值大于左右相邻值的元素。
给你一个输入数组
nums
,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。你可以假设
nums[-1] = nums[n] = -∞
。示例 1:
输入:nums = [1,2,3,1] 输出:2 解释:3 是峰值元素,你的函数应该返回其索引 2。
示例 2:
输入:nums = [1,2,1,3,5,6,4] 输出:1 或 5 解释:你的函数可以返回索引 1,其峰值元素为 2; 或者返回索引 5, 其峰值元素为 6。
提示:
1 <= nums.length <= 1000
-231 <= nums[i] <= 231 - 1
- 对于所有有效的
i
都有nums[i] != nums[i + 1]
**进阶:**你可以实现时间复杂度为
O(logN)
的解决方案吗?
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int left = 0;
int right = nums.size()-1;
while(left<right){
int mid = left + (right - left) / 2;
if (nums[mid] > nums[mid + 1]) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
};
ums[i] != nums[i + 1]`
**进阶:**你可以实现时间复杂度为
O(logN)
的解决方案吗?
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int left = 0;
int right = nums.size()-1;
while(left<right){
int mid = left + (right - left) / 2;
if (nums[mid] > nums[mid + 1]) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
};