【优选算法】(第十二篇)

目录

搜索旋转排序数组中的最⼩值(medium)

题目解析

讲解算法原理

编写代码

0〜n-1中缺失的数字(easy)

题目解析

讲解算法原理

编写代码


搜索旋转排序数组中的最⼩值(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;
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值