algorithm-base/animation-simulation/二分查找及其变种/leetcode 81不完全有序查找目标元素(包含重复值) .md

108 lines
4.3 KiB
Java
Raw Normal View History

2021-07-23 15:44:19 +00:00
> 如果阅读时发现错误或者动画不可以显示的问题可以添加我微信好友 **[tan45du_one](https://raw.githubusercontent.com/tan45du/tan45du.github.io/master/个人微信.15egrcgqd94w.jpg)** ,备注 github + 题目 + 问题 向我反馈
2021-03-20 09:16:07 +00:00
>
> 感谢支持该仓库会一直维护希望对各位有一丢丢帮助
>
2021-07-23 15:44:19 +00:00
> 另外希望手机阅读的同学可以来我的 <u>[**公众号袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入。
2021-03-20 09:16:07 +00:00
2021-03-18 05:33:53 +00:00
## **查找目标元素含重复元素**
我们通过刚才的例子了解了如果在不完全有序的数组中查找目标元素但是我们的不完全有序数组中是不包含重复元素的那如果我们的数组中包含重复元素我们应该怎么做呢见下图
2021-03-21 05:44:19 +00:00
![640](https://img-blog.csdnimg.cn/img_convert/9f77a33a7ff5b3fd8bbb98d77cb8a499.png)
2021-03-18 05:33:53 +00:00
如上图如果我们继续使用刚才的代码则会报错这是为什么呢?我们来分析一下
2021-03-21 05:44:19 +00:00
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210321134336356.png)
2021-03-18 05:33:53 +00:00
2021-07-23 15:44:19 +00:00
所以我们需要对其进行改进我们只需将重复元素去掉即可当我们的 nums[left] == nums[mid] left ++ 即可比如 13111 此时 nums[mid] == nums[left] left ++,那我们此时会不会错过目标值呢其实并不会只是去掉了某些重复元素如果此时我们的目标元素是 3则我们 left++之后情况就变为了上题中的情况
2021-03-18 05:33:53 +00:00
2021-03-20 09:16:07 +00:00
#### [81. 搜索旋转排序数组 II](https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/)
2021-03-18 05:33:53 +00:00
#### **题目描述**
假设按照升序排序的数组在预先未知的某个点上进行了旋转
( 例如数组 [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[mid] == nums[left] left++并退出本次循环其余部分完全相同大家可以结合代码和图片进行理解
#### **题目代码**
```java
class Solution {
public boolean search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = left+((right-left)>>1);
if (nums[mid] == target) {
return true;
}
if (nums[mid] == nums[left]) {
left++;
continue;
}
if (nums[mid] > nums[left]) {
if (nums[mid] > target && target >= nums[left]) {
right = mid - 1;
} else if (target > nums[mid] || target < nums[left]) {
left = mid + 1;
2021-07-23 15:44:19 +00:00
}
2021-03-18 05:33:53 +00:00
}else if (nums[mid] < nums[left]) {
if (nums[mid] < target && target <= nums[right]) {
left = mid + 1;
} else if (target < nums[mid] || target > nums[right]) {
right = mid - 1;
}
2021-07-23 15:44:19 +00:00
}
2021-03-18 05:33:53 +00:00
}
return false;
2021-07-23 15:44:19 +00:00
}
2021-03-18 05:33:53 +00:00
}
```
2021-07-27 18:26:32 +00:00
Go Code:
```go
func search(nums []int, target int) bool {
l, r := 0, len(nums) - 1
for l <= r {
m := l + (r - l) / 2
if nums[m] == target {
return true
}
// 先判断哪边是递增的,再查找范围
if nums[m] == nums[l] {
l++
} else if nums[l] < nums[m] {
// 判断target是否在有序的那边就行了。
if nums[l] <= target && target < nums[m] {
r = m - 1
} else {
l = m + 1
}
} else if nums[l] > nums[m] {
if nums[m] < target && target <= nums[r] {
l = m + 1
} else {
r = m - 1
}
}
}
return false
}
```