【优选算法】(第十二篇)
在传递给函数之前, nums 在预先未知的某个下标 k(0 <= k < nums.length) 上进⾏了旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1],通过图像我们可以发现, [A,B] 区间内的点都是严格⼤于 D 点的值的, C 点的值是严格⼩于 D 点的值的。例如, [0,1,2,4,5,6,7] 在下标 3 处
目录
搜索旋转排序数组中的最⼩值(medium)
题目解析
1.题目链接:. - 力扣(LeetCode)
2.题目描述:
整数数组 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
关于暴⼒查找,只需遍历⼀遍数组,这⾥不再赘述。
讲解算法原理
解法(⼆分查找):
算法思路:
题⽬中的数组规则如下图所⽰:
其中 C 点就是我们要求的点。
⼆分的本质:找到⼀个判断标准,使得查找区间能够⼀分为⼆。
通过图像我们可以发现, [A,B] 区间内的点都是严格⼤于 D 点的值的, C 点的值是严格⼩于 D 点的值的。但是当 [C,D] 区间只有⼀个元素的时候, C 点的值是可能等于 D 点的值的。
因此,初始化左右两个指针 left , right :
然后根据 mid 的落点,我们可以这样划分下⼀次查询的区间:
▪ 当 mid 在 [A,B] 区间的时候,也就是 mid 位置的值严格⼤于 D 点的值,下⼀次查
询区间在 [mid + 1,right] 上;
▪ 当 mid 在 [C,D] 区间的时候,也就是 mid 位置的值严格⼩于等于 D 点的值,下次
查询区间在 [left,mid] 上。
当区间⻓度变成 1 的时候,就是我们要找的结果。
编写代码
c++算法代码:
class Solution
{
public:
int findMin(vector<int>& nums)
{
int left = 0, right = nums.size() - 1;
int x = nums[right]; // 标记⼀下最后⼀个位置的值 while(left < right)
{
int mid = left + (right - left) / 2;
if(nums[mid] > x) left = mid + 1;
else right = mid;
}
return nums[left];
}
};
java算法代码:
class Solution {
public int findMin(int[] nums) {
int left = 0, right = nums.length - 1;
int x = nums[right]; // 标记⼀下最后⼀个位置的值 while(left < right)
{
int mid = left + (right - left) / 2;
if(nums[mid] > x) left = mid + 1;
else right = mid;
}
return nums[left];
}
}
0〜n-1中缺失的数字(easy)
题目解析
1.题目链接:. - 力扣(LeetCode)
2.题目描述:
⼀个⻓度为n-1的递增排序数组中的所有数字都是唯⼀的,并且每个数字都在范围0〜n-1之内。在范围0〜n-1内的n个数字中有且只有⼀个数字不在该数组中,请找出这个数字。
⽰例1:
输⼊:[0,1,3]
输出:2
⽰例2:
输⼊:[0,1,2,3,4,5,6,7,9]
输出:8
限制:
1<=数组⻓度<=10000
讲解算法原理
解法(⼆分查找算法):
算法思路:
关于这道题中,时间复杂度为 O(N) 的解法有很多种,⽽且也是⽐较好想的,这⾥就不再赘述。本题只讲解⼀个最优的⼆分法,来解决这个问题。
在这个升序的数组中,我们发现:
▪ 在第⼀个缺失位置的左边,数组内的元素都是与数组的下标相等的;▪ 在第⼀个缺失位置的右边,数组内的元素与数组下标是不相等的。
因此,我们可以利⽤这个「⼆段性」,来使⽤「⼆分查找」算法。
编写代码
c++算法代码:
class Solution
{
public:
int missingNumber(vector<int>& nums)
{
int left = 0, right = nums.size() - 1;
while(left < right)
{
int mid = left + (right - left) / 2;
if(nums[mid] == mid) left = mid + 1;
else right = mid;
}
return left == nums[left] ? left + 1 : left;
}
};
java算法代码:
class Solution {
public int missingNumber(int[] nums) {
int left = 0, right = nums.length - 1;
while(left < right) {
int mid = left + (right - left) / 2;
if(nums[mid] == mid) left = mid + 1;
else right = mid;
}
return left == nums[left] ? left + 1 : left;
}
}
更多推荐
所有评论(0)