Template 2 是让最后一步只剩2个值,一个是left pointer,另一个是right pointer。如果不管哪个,若和目标值不一致,则两个pointer合并为一个,最后terminate while循环,并post process最后一个值是否与目标值同。不同则输出-1。
(Q:暂时没理解为啥和template 1 不同?先🐴)
# 278 First Bad Version
You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of your product fails the quality check. Since each version is developed based on the previous version, all the versions after a bad version are also bad.
Suppose you have n
versions [1, 2, ..., n]
and you want to find out the first bad one, which causes all the following ones to be bad.
You are given an API bool isBadVersion(version)
which returns whether version
is bad. Implement a function to find the first bad version. You should minimize the number of calls to the API.
第一次写的:
# The isBadVersion API is already defined for you.
# def isBadVersion(version: int) -> bool:
class Solution:
def firstBadVersion(self, n: int) -> int:
l, r = 0, n
while r - l > 1:
mid = (l + r)//2
if isBadVersion(mid):
l = mid
else:
r = mid
return r
submit之后说n = 2, bad =1的情况下不符。
发现是我的解法是,terminate的条件是最后剩两个值,左边是最后一个good version,右边是第一个bad version。但我这种思路是默认Left pointer所杵的位置一定是good version,right pointer所杵的位置是bad version。所以test case中一旦left pointer起始位置就是bad version,就会输出错误的结果。
只能换一种terminate方式。left 与right pointer 合为一个再输出。l = mid + 1。这样剩一个值的时候一定是我们要的first bad version的值。
改了之后的runtime:
sample solution:
本质没区别。不分析了。
#162 Find Peak Element
A peak element is an element that is strictly greater than its neighbors.
Given an integer array nums
, find a peak element, and return its index. If the array contains multiple peaks, return the index to any of the peaks.
You may imagine that nums[-1] = nums[n] = -∞
.
You must write an algorithm that runs in O(log n)
time.
解题思路是最后剩一个值,这个值就是所求peak的index。
中值取法是左右标之和加1除以2,相当于最后剩两值时,mid与右标相等。
筛选条件是mid比左边的值大就挪left pointer至中值。反之则右标挪至中值左邻的位置。
class Solution:
def findPeakElement(self, nums: List[int]) -> int:
l, r = 0, len(nums)-1
while r > l:
mid = (r+l+1)//2
if nums[mid] > nums[mid-1]:
l = mid
else:
r = mid - 1
return l
runtime:
sample:
中值少了+1一步。不过改了之后
class Solution:
def findPeakElement(self, nums: List[int]) -> int:
l, r = 0, len(nums)-1
while r > l:
mid = (r+l)//2
if nums[mid] > nums[mid+1]:
r = mid
else:
l = mid + 1
return l
反而更慢了。比较玄学……
算了,以后sample解法相差不大的就不分析也不提了。
#153 Find Minimum in Rotated Sorted Array
解题思路:
不考虑rotated了多少次,只判断最小值在中值左边还是右边。判别方法,中值与尾值比大小:> 则在右边。反之则反。最后terminate的condition是左标右标合一,最后剩最小值。
class Solution:
def findMin(self, nums: List[int]) -> int:
l, r = 0, len(nums)-1
while r > l:
mid = (l + r)//2
if nums[mid] > nums[-1]:
l = mid + 1
else:
r = mid
return nums[l]
runtime:
和31ms的解法一样。就不分析了。