局部有序的:
33,81,153.
局部有序的和找左右边界写法不太一样,要先判断哪边是有序的。
局部有序的还是用闭区间写法比较方便,要判断nums[right] >= target,开区间写法会越界
单调有序找左右边界的:
34,35
35. 搜索插入位置
二分的两种写法:开区间和闭区间
闭区间写法
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
#闭区间写法
left = 0
right = len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
elif nums[mid] > target:
right = mid - 1
else:
left = mid + 1
#如果不存在,返回left,因为left的条件是nums[mid] < target:left = mid + 1
#此时的mid是比target小的那个元素
return left
开区间写法
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
#开区间写法,一般用right=mid那种写法
left = 0
right = len(nums)
while left < right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
elif nums[mid] > target:
right = mid
else:
left = mid + 1
return left
33. 搜索旋转排序数组
二分的两种写法:开区间和闭区间
class Solution:
def search(self, nums: List[int], target: int) -> int:
#闭区间写法。
left = 0
right = len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
#左区间升序
if nums[left] <= nums[mid]:
#target在左边区间里
if nums[left] <= target and nums[mid] >= target:
right = mid - 1
else:
left = mid + 1
#右区间升序
else:
if nums[mid] <= target and nums[right] >= target:
left = mid + 1
else:
right = mid - 1
return -1
开区间写法
class Solution {
public int search(int[] nums, int target) {
int n = nums.length;
int idx = 0;
for (int i = 0; i < n - 1; i++) {
if (nums[i] > nums[i + 1]) {
idx = i;
break;
}
}
int ans = find(nums, 0, idx, target);
if (ans != -1) return ans;
if (idx + 1 < n) ans = find(nums, idx + 1, n - 1, target);
return ans;
}
int find(int[] nums, int l, int r, int target) {
while (l < r) {
int mid = l + r >> 1;
if (nums[mid] >= target) {
r = mid;
} else {
l = mid + 1;
}
}
return nums[l] == target ? l : -1;
}
}
作者:AC_OIer
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/solution/shua-chuan-lc-yan-ge-ologn100yi-qi-kan-q-xifo/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
81. 搜索旋转排序数组 II
class Solution:
def search(self, nums: List[int], target: int) -> bool:
left = 0
right = len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return True
#去重
if nums[left] == nums[mid] == nums[right]:
left += 1
right -= 1
# 左边升序
elif nums[mid] >= nums[left]:
# 如果target在左边
if nums[mid] > target and nums[left] <= target:
right = mid - 1
else:
left = mid + 1
# 右边升序
else:
# 如果target在右边
if nums[mid] < target and nums[right] >= target:
left = mid + 1
else:
right = mid - 1
return False
153. 寻找旋转排序数组中的最小值
为什么要mid和right比,而不能mid和left比
应该是left的时候没办法判断到底怎么移动,比如说left是10 mid是 15 不知道left是不是就是最小了还是最小在mid后。比如10 15 20就可以
class Solution(object):
def findMin(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
left = 0
right = len(nums) - 1
while left <= right:
mid = (left + right) // 2
#最小值在左半边,mid可能是最小值
if nums[mid] < nums[right]:
right = mid
#最小值在右半边,mid不可能是最小值
else:
left = mid + 1
return nums[right]
154
153的基础上去重