注册一亩三分地论坛,查看更多干货!
您需要 登录 才可以下载或查看附件。没有帐号?注册账号 
x
我最开始对于二分搜索的印象就是CS50里面professor撕书的场面。 CS50的professor 要找一个电话号码, 他每次都可以根据条件撕掉书剩下的一半。 最后书只剩下一页, 他也找到了自己想要的号码。
这个就是binary search的真谛。 根据条件排除另外一半, 留下我们想要的一半。最后剩下的, 就是我们想要的。
以下是binary search的code.
- def binary_search(self, nums, target):
- start, end = 0, len(nums)-1
- while (start + 1 < end):
- mid = start + (end - start) // 2 if nums[mid] == target:
- return mid
- # 当我们知道target比middle value来得大, 而且整个array是sorted, 我们可以知道答案只在右边那一半, 所以我们舍弃左边。 把start pointer移到右边那一半的开始。
- elif nums[mid] < target:
- start = mid
- # 同理, 当我们知道target比middle value小, 我们舍弃右边那一把。 把end pointer 移到左边那一半的结尾。
- else:
- end = mid
- if nums[end] == target:
- return end
- if nums[start] == target:
- return start
- return -1
复制代码
leetcode 34 https://leetcode.com/problems/fi ... nt-in-sorted-array/
- class Solution(object):
- def searchRange(self, nums, target):
- """
- :type nums: List[int]
- :type target: int
- :rtype: List[int]
- """
- if nums is None or len(nums) == 0:
- return [-1, -1]
- return [self.find_first(nums, target), self.find_last(nums, target)]
- def find_last(self, nums, target):
- """
- :rtype: int
- """
- start, end = 0, len(nums)-1
- while (start + 1 < end):
- mid = start + (end - start) // 2
- # 当我们得知target和middle value相等, 我们可以确定右边那一半是我们想要的, 我们舍弃左边那一半。
- # 右边那一半肯定放着 the last index of target。
- # 这么说的原因是因为 右边那一半已经至少有一个与target相等的值, 现在只有两种情况, 一个是右边那一半只有一个与target相等的值, 那么我们也已经包括把最终答案包括在右边。
- # 另外一种情况是右边那一半有多个与target相等的值, 那种情况我们也是已经把最终答案包括在右边 (因为这个题目要求的是last index of the element)。
- # 同理可以推导出find_first_index
- if nums[mid] == target:
- start = mid
- elif nums[mid] < target:
- start = mid
- else:
- end = mid
-
- if nums[end] == target:
- return end
- if nums[start] == target:
- return start
- return -1
-
- def find_first(self, nums, target):
- """
- : rtypes: int
- """
- start, end = 0, len(nums) - 1
- while start + 1 < end:
- mid = start + (end - start) // 2
- if nums[mid] == target:
- end = mid
- elif nums[mid] > target:
- end = mid
- else:
- start = mid
- if nums[start] == target:
- return start
- if nums[end] == target:
- return end
- return -1
复制代码
同样的道理可以放在 search in rotated sorted array - https://leetcode.com/problems/search-in-rotated-sorted-array/
这道题目 我们主要要知道怎么提取出条件, 这个条件就是用来舍弃另外一半的条件。
我们通常知道sorted in order是一个很重要的提示, 这个是在提示我们可以用binary search, 因为sorted可以作为舍弃另外一半的条件。
这个题目的条件是rotated sorted array, 他也有sorted的部分。 我们可以做的就是只在sorted的地方用binary search
- class Solution(object):
- def search(self, nums, target):
- """
- :type nums: List[int]
- :type target: int
- :rtype: int
- """
- if not nums or not len(nums):
- return -1
-
- start, end = 0, len(nums)-1
- while start+1 < end:
- mid = (start+end)//2
- if nums[mid] == target:
- return mid # 一共会有两种rotated的情况, 一个是前面那一半是sorted, 一个是后面那一半才是sorted
- # e.g [1, 2, 3, 4, 5, 6] => [2, 3, 4, 5, 6, 1] or [5, 6, 1, 2, 3, 4] 这两个都是rotated sorted, 不过一个是前面那一半那个是perfectly sorted, 一个是后面那一半perfectly sorted
- if nums[mid] <= nums[end]: # mid to end is in ascending order
- # 现在我们可以确认这一半是perfectly sorted
- # 我们现在判断target是否在这一半里面, 如果不是, 我们就舍弃这一半
- if nums[mid]<= target <= nums[end]:
- start = mid
- else:
- end = mid
- else: # start to mid is in ascending order
- if nums[start] <= target <= nums[mid]:
- end = mid
- else:
- start = mid
- if nums[start] == target:
- return start
- if nums[end] == target:
- return end
- return -1
复制代码
最后总结一下binary search, binary search真谛就是舍弃另外一半, 然后取我们要的那一半, 再在最后剩下的东西里面挑我们要的。
在所有binary search题目里面,我们要发现可以用来舍弃另外一半的条件。
最后求米
|