1. Binary search
- sorted, or indirectly sorted
- Pay attention to the boundary conditions, since only one condition is triggered per loop, so iii orjjj can only move one step, the loop condition isi ≤ ji\le ji≤j
training plan
Subject: 704. Binary Search
Code template:
class Solution:
def search(self, nums: List[int], target: int) -> int:
i, j = 0, len(nums)-1
while i <= j:
# 取靠左的,即 1 2 3 4 取2,1 2 3 取2
# 防止计算时溢出
mid = i + ((j-i) >> 1)
if nums[mid] == target:
return mid
elif nums[mid] < target:
i = mid+1
else:
j = mid-1
return -1
Title: 278. The first wrong version
Code template:
# The isBadVersion API is already defined for you.
# @param version, an integer
# @return an integer
# def isBadVersion(version):
class Solution:
def firstBadVersion(self, n):
"""
:type n: int
:rtype: int
"""
# 特殊之处在于只有2种状态,即当跳出循环时:
# 如果是i未出错,i += 1,返回i;如果j未出错,一定是上一个版本出错,也返回i
i, j = 1, n
while i <= j:
mid = i + ((j-i) >> 1)
if isBadVersion(mid):
j = mid-1
else:
i = mid+1
return i
This question can also use i < j i<ji<The condition of j is judged, and only one pointer moves at a time.
Why is there such a difference ? In fact, it is because of the different interval conditions of dichotomy. There are 3 situations for judging the number. When the final range length is greater than 0, it is the valid range; but there are only 2 cases for judging true or false. Only when the range length is 1 is the final answer. Here we need to think carefully and generalize the problem to various situations.
Topic: 35. Search insertion position
Code template:
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
# 3种情况,对比普通二分将返回-1变为返回合适的索引
# 考虑找不到的情况,此时i=j,并且有一个变化使while条件不成立,大了j减1,小了i+1,所以返回i
# 插入位置i表示插入到i索引之前
i, j = 0, len(nums)-1
while i <= j:
mid = i + ((j-i) >> 1)
if nums[mid] == target:
return mid
elif nums[mid] < target:
i = mid+1
else:
j = mid-1
return i
similar topic
Topic: 34. Find the first and last position of an element in a sorted array (emphasis)
Code template:
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
# i和j就是区间2端点
# 3种情况
i, j = 0, len(nums)-1
while i <= j:
mid = i + ((j-i) >> 1)
if nums[mid] < target:
i = mid + 1
elif nums[mid] > target:
j = mid - 1
# mid到j都等于target
elif nums[i] != target:
i += 1
# i到mid都等于target
elif nums[j] != target:
j -= 1
else:
return [i, j]
return [-1, -1]
This question is more interesting. My implementation is not a complete binary search, but to a certain extent, the use of binary search optimizes the overall efficiency. If you have time, you can learn the official solution
Topic: 374. Guessing the Size of Numbers
Code template:
# The guess API is already defined for you.
# @param num, your guess
# @return -1 if my number is lower, 1 if my number is higher, otherwise return 0
# def guess(num: int) -> int:
class Solution:
def guessNumber(self, n: int) -> int:
i, j = 1, n
while i <= j:
mid = i + ((j-i) >> 1)
if guess(mid) == 0:
return mid
elif guess(mid) == -1:
j = mid-1
else:
i = mid+1
# 返回0表示pick不在范围内
return 0
Topic: 658. Find the K closest elements (check the coding ability)
Code template:
class Solution:
def findClosestElements(self, arr: List[int], k: int, x: int) -> List[int]:
# 二分找到恰好大于x一点点的位置,等价于之前的查找插入位置
i, j = 0, len(arr)-1
idx = -100
while i <= j:
mid = i + ((j-i) >> 1)
if arr[mid] == x:
idx = mid
break
elif arr[mid] < x:
i = mid+1
else:
j = mid-1
if idx == -100:
idx = i
# print(idx)
# 缩小区间
if idx == 0:
return arr[:k]
elif idx == len(arr):
return arr[-k:]
else:
i, j = max(idx-k, 0), min(idx+k, len(arr)-1)
while j-i >= k:
if arr[j] - x > x - arr[i]:
j -= 1
elif arr[j] - x < x - arr[i]:
i += 1
else:
j -= 1
return arr[i:j+1]