刚自学完 Codecademy 的数据结构,因为上面的随练比较少,加上对知识点的掌握和理解还不够,所以开始在 Leetcode 上根据 b站 Christinaaaya 的建议,按知识板块从易到难做题。
用的是 Leetcode 上 explore 版块,先从 binary search 入手。
背景一章,给的是 #704.
题目:
Given an array of integers nums
which is sorted in ascending order, and an integer target
, write a function to search target
in nums
. If target
exists, then return its index. Otherwise, return -1
.
You must write an algorithm with O(log n)
runtime complexity.
第一次写的是:
class Solution:
def search(self, nums: List[int], target: int) -> int:
while nums is not None:
mid = len(nums) // 2
if nums[mid] == target:
return mid
if len(nums) != 1:
if nums[mid] > target:
nums = nums[:mid]
else:
nums = nums[mid+1:]
else:
return -1
test case 是
[-1,0,3,5,9,12] 9
结果 output 是 0 ,而 expected output 是 4 .
才意识我这么 truncate 会改掉原 index ,这不是题目要的。如果要保留原 index ,同时能不断缩小范围,就不能用 nums 储存缩小的信息。后来对比 solution ,才想起来,应该用 pointer 。于是改成这样:
class Solution:
def search(self, nums: List[int], target: int) -> int:
left, right = 0, len(nums) - 1
while left < right:
pivot = (right + left) // 2
if nums[pivot] == target:
return pivot
elif nums[pivot] > target:
right = pivot - 1
else:
left = pivot + 1
return -1
用 left,right 框柱缩小范围的信息。run code 结果显示 accepted。submit 显示有误。
问题出在当 left 和 right 重合时,没有判断最后一个值是否是 target 就默认 -1 .导致错判。
while 的 condition 里补上 = 之后再 submit ,accepted 。但是 runtime 结果只处于 42.94% 。
于是打开位于前列的解法:
对比后,发现这个解法和我的不同之处在于:
1.合并了 return 这步输出
把判断和 target 值相不相等放在了 while 循环之外。
这个更快的解法的 while 的 condition 并不包含 = ,这意味着循环之外左标 left 和右标 right 合并了。合并之后剩最后一个值再判断是不是target。因此省去了循环里反复看中间值是不是target的这一步。
2.pivot的取值方式不同
取中值他的做法是以左标为锚点,然后加差值加一的一半。
我直接左标右标index值之和取一半。
有何不同?
用我的方法的话,当剩到最后左标和右标相邻时,pivot还是等于左标。
若左标小于或等于目标值,那左标永远不移动。这会造成左标index永远小于右标index,而走不出循环。所以我那种取中值方式不可取。
因此我第三次写成了:
class Solution:
def search(self, nums: List[int], target: int) -> int:
left, right = 0, len(nums) - 1
while left <= right:
pivot = left + (right - left + 1) // 2
if nums[pivot] > target:
right = pivot - 1
else:
left = pivot
return left if nums[left] == target else -1
可是runtime却是70.55%。
明明是一样的解法,runtime结果还是不同。于是我谷歌了一下why leetcode Accepted Solutions Runtime Distribution diff every time:Loading...Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.https://leetcode.com/discuss/general-discussion/136683/different-run-time-with-same-code原来是大家都遇到了这个问题,算是leetcode的一个bug。
那就只把runtime result当做相对参考,以及学习其中更优解的思路。