第9天
1.0704.二分查找
描述:给定一个升序的数组nums,和一个目标值target。
要求:返回target在数组中的位置,如果找不到,则返回 -1。
class Solution:
def search(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums) - 1
while left <= right :
mid = (left + right) // 2
if target == nums[mid] :
return mid
elif target > nums[mid] :
left = mid +1
elif target <nums[mid] :
right = mid -1
return -1
反思:这一题对于刚刚解除二分查找的新手可谓是十分友好而且十分经典了。在有序数组中通过与中心值进行比较,从而确定一个target存在的区间,再进行循环确定,缩小target存在的范围。
2.35.搜索插入位置
描述:给定一个排好序的数组nums,以及一个目标值 target。
要求:在数组中找到目标值,并返回下标。如果找不到,则返回目标值按顺序插入数组的位置。
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums) - 1
mid_1 = (left + right) // 2
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid + 1
elif nums[mid] > target:
right = mid - 1
return left
反思: 做这道题时,我想复杂了,以为如果没找到目标的下标,就要插入到合适的位置,结果把程序写复杂了,到最后也没能输出正确的结果,无奈看了题解,才发现不需要如此麻烦,就把代码进行了删改。
3.0374.猜数字大小
描述:猜数字游戏。给定一个整数n和一个接口 def guess(num: int) -> int:
,题目会从 1∼n中随机选取一个数x。我们只能通过调用接口来判断自己猜测的数是否正确。
要求:要求返回题目选取的数字x。
# The guess API is already defined for you.
# @param num, your guess
# @return -1 if num is higher than the picked number
# 1 if num is lower than the picked number
# otherwise return 0
# def guess(num: int) -> int:
class Solution:
def guessNumber(self, n: int) -> int:
left =1
right = n
while left <= right:
mid = (left + right ) // 2
result = guess(mid)
if result == -1 :
right = mid -1
elif result == 1:
left = mid +1
else:
return mid
反思: 在做这道题时,一开始我还不理解题目的意思,这个接口到底该怎么调用呢?于是去看了一下题解才知道可以直接使用,那就好办了,使用二分法就能马上解决。
第10天
1.0069.x的平方根
要求:实现 int sqrt(int x)
函数。计算并返回x的平方根(只保留整数部分),其中x是非负整数。
class Solution:
def mySqrt(self, x: int) -> int:
left = 1
right =x
res = 0
if x*x == x:return x
while left <= right:
mid = (left + right ) // 2
if mid*mid <=x:
res = mid
left = mid +1
elif mid*mid >x:
right = mid -1
return res
反思:经过这两天的学习已经能够有感觉的使用二分查找了,当第一次见到这题时,脑海中是有思路的,当修修改改终于完成之后,却通过不了,有修改了几次还不行。于是就看看题解里的方法,发现大差不差,借鉴之后终于通过了。
2.0167.两数之和Ⅱ-输入有序数组
描述:给定一个下标从 1 开始计数、升序排列的整数数组:numbers和一个目标值target。
要求:从数组中找出满足相加之和等于target的两个数,并返回两个数在数组中下的标值。
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
if numbers == []:
return []
res = []
n = len(numbers)
left = 0
right = n-1
while left < right:
if numbers[left] + numbers[right] == target :
return [left + 1,right + 1]
elif numbers[left] + numbers[right] > target :
right -=1
else: left +=1
反思: 在做这道题时,一开始是有思路的,我的想法是:先找出比target小的数所在的区间,在从头到尾开始判断,但是结果是测试没通过,也不能解决问题。于是浏览了一些题解后,终于把思路弄清晰了,最后把问题解决。
3.1011.在D天内送达包裹的能力
class Solution:
def shipWithinDays(self, weights: List[int], D: int) -> int:
def check(val):
c, tol = 1, 0
for w in weights:
tol += w
if tol > val:
tol = w
c += 1
return c <= D
l, r = max(weights), sum(weights)
while l < r:
val = (l + r) >> 1
if check(val): r = val
else: l = val + 1
return l
反思: 看到这题时,其实大脑是有点迷蒙的状态,我在哪/我要干什么?思考无果后,只能去求助题解,看看别人的思路。这道题其实也是用了二分法,只不过把范围化成了船舶的载重量,最大是所有货物(即一天完成)最小是货物当中重量最大的。怎么说呢,学到了很多,感到二分也能这么用。
第11天
1.0278.第一个错误的版本
描述:给你一个整数n,代表已经发布的版本号。还有一个用于检测版本是否出错的接口 isBadVersion(version):
。
要求:找出第一次出错的版本号bad。
# The isBadVersion API is already defined for you.
# def isBadVersion(version: int) -> bool:
class Solution:
def firstBadVersion(self, n: int) -> int:
left = 1
right = n
while left <= right:
mid = (left +right )//2
if isBadVersion(mid):
right = mid -1
else:
left = mid +1
return left
反思: 在写这道题时,一开始的思路是有的但就是不能解决问题,对于测试是可以通过,但是对一些例子通不过。看了题解后,再对程序进行改进,才发现原来是弄复杂了。
2.0033.搜索旋转排序数组
描述:给定一个整数数组nums,数组中值互不相同。给定的nums是经过升序排列后的又进行了「旋转」操作的。再给定一个整数target。
要求:从nums中找到target所在位置,如果找到,则返回对应下标,找不到则返回 −1。
class Solution:##这是第一次写的题解,虽然可以通过,但是时间复杂度是O(n)
def search(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums)
while left < right:
result = target in nums
if result:
mid = (left + right) //2
res_1=nums[left:mid]
if target in res_1:
for i in range(len(res_1)):
if target == res_1[i]:
return i
else:
for i in range(mid,right):
if target == nums[i]:
return i
else:
return -1
class Solution:
def search(self, nums: List[int], target: int) -> int:
if len(nums) <=0:
return -1
left = 0
right = len(nums)-1
while left <= right:
mid = (left + right)//2
if nums[mid] == target:
return mid
elif nums[left] <= nums[mid]:
if nums[left] <= target < nums[mid]:
right = mid - 1
else:
left = mid + 1
else:
if nums[mid] < target <= nums[right]:
left = mid + 1
else:
right = mid - 1
return -1
反思:这题一开始是做出来了,不过时间复杂度却不符合要求,苦想了挺久也没想出如何更好的解决。浏览了一些题解才知道,原来是从mid与第一个元素的大小来判断mid属于哪个区间,然后在这个确定的区间里进行二分查找。
3.0153.寻找旋转排序数组中的最小值
描述:给定一个数组nums,nums是有升序数组经过「旋转」得到的。但是旋转次数未知。数组中不存在重复元素。
要求:找出数组中的最小元素。
class Solution:
def findMin(self, nums: List[int]) -> int:
if len(nums) == 1:
return nums[0]
low, high = 0, len(nums) - 1
nums_min = float('inf')
while low <= high:
mid = low + (high - low) // 2
if nums[mid] < nums_min:
nums_min = nums[mid]
if nums[low] < nums[mid]:
if nums_min > nums[low]:
nums_min = nums[low]
low = mid + 1
else:
if nums_min > nums[high]:
nums_min = nums[high]
high = mid - 1
return nums_min
反思:做到这道题,一开始是没有思路的,以为像之前做过的矩阵旋转一样,到头来却不是。浏览了题解后,终于跟着大佬的题解一步一步弄明白了。
Task04总结
坚持到了Task04。这次学习的二分查找算法,感觉相比之前学到的排序方法而言,敢于动手解决的勇气有所增加,题目的难度也有所降低,放缓了紧张的状态。因为每一道练习,都是使用二分查找来解决,知识点比较集中,感到自己的编程能力也得到了一些提升。Task04,就像游戏里过关斩将一般,有挑战性但也不是束手无策,每一次看到提交通过,我都会很开心。o(* ̄▽ ̄*)ブ