[TOC]
刷了4道Binary Search Easy难度的题
二叉搜索思想好想,难在边界的控制上,于是乎我就在思考能不能背下一个定式,遇到二分搜索的题目就套这个定式。
我做的第一道二叉搜索的题目就是一个很好的定式:
#744. Find Smallest Letter Greater Than Target
Given a list of sorted characters letters
containing only lowercase letters, and given a target letter target
, find the smallest element in the list that is larger than the given target.
Letters also wrap around. For example, if the target is target = 'z'
and letters = ['a', 'b']
, the answer is 'a'
.
Examples:
Input: letters = ["c", "f", "j"] target = "a" Output: "c" Input: letters = ["c", "f", "j"] target = "c" Output: "f" Input: letters = ["c", "f", "j"] target = "d" Output: "f" Input: letters = ["c", "f", "j"] target = "g" Output: "j" Input: letters = ["c", "f", "j"] target = "j" Output: "c" Input: letters = ["c", "f", "j"] target = "k" Output: "c"
Note:
letters
has a length in range[2, 10000]
.letters
consists of lowercase letters, and contains at least 2 unique letters.target
is a lowercase letter.
class Solution(object):
def nextGreatestLetter(self, letters, target):
"""
:type letters: List[str]
:type target: str
:rtype: str
"""
low = 0
high = len(letters)
while (low < high) :
mid = low + (high - low) / 2
if (letters[mid] <= target):
low = mid + 1
else: high = mid
return letters[low % len(letters)]
这里面的low,high都是指脚标
34 . Search for a Range
Given an array of integers sorted in ascending order, find the starting and ending position of a given target value.
Your algorithm's runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1]
.
For example,
Given [5, 7, 7, 8, 8, 10]
and target value 8,
return [3, 4]
.
class Solution(object):
def searchRange(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
if len(nums)==0:#空输入处理
return [-1,-1]
low = 0
high = len(nums)
while (low < high):
mid = low + int((high - low) / 2)
if (nums[mid] <= target):
low = mid + 1
else:
high = mid
start=low-1#target所在的位置,因为low是比target大的数中最小的一个
end=low-1#target所在的位置,因为low是比target大的数中最小的一个
if (nums[end] != target ):#target不存在于数组中
return [-1,-1]
else:#target存在于数组中
while (start != 0 and nums[start] == nums[start - 1]):#看看start左边是不是还有一样的值
start = start - 1
return [start,end]
完美地套用了我们的定式,
最后的if -else分支是根据本题再做的逻辑补充
374.Guess Number Higher or Lower
We are playing the Guess Game. The game is as follows:
I pick a number from 1 to n. You have to guess which number I picked.
Every time you guess wrong, I'll tell you whether the number is higher or lower.
You call a pre-defined API guess(int num)
which returns 3 possible results (-1
, 1
, or 0
):
-1 : My number is lower 1 : My number is higher 0 : Congrats! You got it!
Example:
n = 10, I pick 6. Return 6.
# 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):
class Solution(object):
def guessNumber(self, n):
"""
:type n: int
:rtype: int
"""
low=1#Low index
high=n+1#high index
while (low<high):
mid=low+int((high-low)/2)
if (guess(mid)==1):#mid<=target
low=mid+1
elif(guess(mid)==-1):
high =mid
elif(guess(mid)==0):
return mid
排序的数组不是nums参数的形式,而是给了一个参数n,对应数组1,2,....n
high在这里还是指向 数组最后一个数还往后移一位
仍然符合定式
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 will return 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.
# @param version, an integer
# @return a bool
# def isBadVersion(version):
class Solution(object):
def firstBadVersion(self, n):
"""
:type n: int
:rtype: int
"""
low=1#low_index
high=n+1#high_index
while(low<high):
mid=low+int((high-low)/2)
if(isBadVersion(mid)==True):
high=mid
else:
low=mid+1
return low
因为现在比如对于 1, 2, 3这个数组
脚标low =1,high=4 类比可得应该return low
并不是实际上的 low_index=0 ,high_index=3 return low-1
依然是定式的变形
总结:
记住定式的套路(<= ,等啊不等啊什么的)
依据题意和实际情况改一下low,high的初始值
和return的值
这个套路目前为止没失败过
难度升级:
Leetcode153. Find Minimum in Rotated Sorted Array
Medium难度,剑指OFFER面试题8(旋转数组的最小数字)
我的解法(根据剑指OFFER的C++改编的Python解法)
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).
Find the minimum element.
You may assume no duplicate exists in the array.
class Solution(object):
def findMin(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if len(nums)==0:
return 0
i=0#指向前部分递增序列第一个数的指针
j=len(nums)-1#指向后部分递增序列最后一个数的指针
indexmid=i#当第一个数小于最后一个数的时候,证明该数组没有旋转过,返回indexmid,所以把indexmid赋初值为i
while(nums[i]>=nums[j]):
if (j-i)==1:
indexmid=j
break
else:
indexmid=(i+j)/2
if nums[i]==nums[j] and nums[indexmid]==nums[i]:#数组的第一个数和最后一个数和中间的数一样,即没有办法通过nums[mid]的大小判断它在哪个部分
result=nums[i]#result保存当前的最小值
for pointer in range(i+1,j+1):
if result>nums[pointer]:
result=nums[pointer]
return result
if nums[indexmid]>=nums[i]:#mid处于前部分增的序列里
i=indexmid
elif nums[indexmid]<nums[j]:#mid处于后部分增的序列里
j=indexmid
return nums[indexmid]
考点:测试用例设计的完善与否,考虑以下几种特殊情况:
->[1,0,1,1,1][1,1,1,0,1]这种start=mid=end的情况
难点:我以前只知道二分搜索可以用在有序搜索上,但以前遇到的都是全局有序,这种局部有序的问题没有思考过!局部有序也是有序,也可以用二分法(可能需要配合On的遍历,如例题)