Skip to content

Commit

Permalink
[add] 81
Browse files Browse the repository at this point in the history
  • Loading branch information
D0ub1ePieR committed Apr 8, 2020
1 parent 34c41ea commit 7950441
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# python3
# medium
# 数组 二分查找
# 36ms 92.63%
# 14MB 8.00%

class Solution:
def search(self, nums: List[int], target: int) -> bool:
nums = list(set(nums))
left, right = 0, len(nums) - 1
if nums == []:
return False
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return True

if nums[mid] >= nums[left]:
if nums[left] <= target < nums[mid]:
right = mid - 1
else:
left = mid + 1
else:
if nums[mid] < target <= nums[right]:
left = mid + 1
else:
right = mid - 1
return False

# 40ms 82.96%
# 13.7MB 8.20%

class Solution:
def search(self, nums: List[int], target: int) -> bool:
if nums == []:
return False
index = 0
while index < len(nums)-1 and nums[index] < target and nums[index] <= nums[index+1]:
index += 1
if nums[index] == target:
return True
mid = index
index = len(nums) - 1
while nums[index] > target and index > mid:
index -= 1
if nums[index] == target:
return True
return False

# 44ms 72.41%
# 13.9MB 8.20%

class Solution:
def search(self, nums: List[int], target: int) -> bool:
return target in nums
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# 81、搜索旋转排序数组II
> tag: python 、 数组 、 二分查找
***
### 题目描述

&emsp;&emsp;假设按照升序排序的数组在预先未知的某个点上进行了旋转。

&emsp;&emsp;( 例如,数组 `[0,0,1,2,2,5,6]` 可能变为 `[2,5,6,0,0,1,2]` )。

&emsp;&emsp;编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 `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 可能包含重复元素。

* 这会影响到程序的时间复杂度吗?会有怎样的影响,为什么?

***
### 题目连接
[81.搜索旋转排序数组II](https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/)

***
### 题解

[搜索旋转排序数组](../33-Search_in_Rotated_Sorted_Array-搜索旋转排序数组) 类似,直接将三种方法转移至这道题中。由于这道题只要返回 `True``False`,以及可能会出现相同的数字,还需要对方法进行一定的修改。

* **函数**

&emsp;&emsp;因为只要返回 `target` 是否在数组中即可,因此不需要考虑数组的顺序直接返回即可。

```python
return target in nums
```

&emsp;&emsp;最终结果,*运行时间44ms*,超过72.41%;*占用内存13.9MB*,超过8.20%。

* **线性查找**

&emsp;&emsp;在原来的基础上由于可能会出现相同的数字,则要在判断排序旋转点的位置时,不需要为严格递增,只要大于等于即可

```python
class Solution:
def search(self, nums: List[int], target: int) -> bool:
if nums == []:
return False
index = 0
while index < len(nums)-1 and nums[index] < target and nums[index] <= nums[index+1]: # < --> <=
index += 1
if nums[index] == target:
return True
mid = index
index = len(nums) - 1
while nums[index] > target and index > mid:
index -= 1
if nums[index] == target:
return True
return False
```

&emsp;&emsp;最终结果,*运行时间40ms*,超过82.96%;*占用内存13.7MB*,超过8.20%。

* **二分查找**

&emsp;&emsp;由于可能会出现相同的数字,所以在判断 `mid` 左右两侧是否已经按顺序排布的时候会产生错误,例如

```
[1, 2, 1, 1, 1]
| | |
left mid right
```

于是,用一个简单的方法,直接将 `nums` 数组转变为 `set` 集合,在转换为 `list` 数组,执行原来的步骤便可以很快的将方法转换问题。

```python
nums = list(set(nums))
```

&emsp;&emsp;最终结果,*运行时间36ms*,超过92.63%;*占用内存14MB*,超过8.00%。可以发现当可能有重复数字出现时,二分查找的时间复杂度优势便体现了出来。主要原因可能是

- 当不存在重复元素的时候,数组最大值为 `k`,那么数组最多只有 `k` 个元素,这时查找 `k` 次和 `log(k)` 次的差距可能不会很大,尤其当 `k` 较小的时候,实际上测试用例中的数组元素有很多也不是很大

- 当存在重复元素的时候,不论是用 `python` 的数组查找还是线性的查找,对于重复元素都要进行重复的操作,而二分查找虽然不会对重复元素进行区分,但是大量的重复元素会导致数组元素上界会很大, `log(k)` 的优势便会体现出来

0 comments on commit 7950441

Please sign in to comment.