前言
今天是打卡的第一天,主要时间还是花在写博客上。希望能坚持下去。
一、704.二分查找?
文档讲解:代码随想录
思路:在考研408的时候已经能手撕二分查找的代码了,但对于区间的定义没有理解清楚
python代码
from typing import List
class Solution:
def search_1(self, nums: List[int], target: int) -> int:#左右均闭合,[left, right]
left, right = 0, len(nums) - 1
while left <= right:#因为left == right是有意义的,所以使用 <=
middle = (left + right) // 2
if nums[middle] > target:
right = middle - 1
elif nums[middle] < target:
left = middle + 1
else:
return middle
return -1
def search_2(self,nums: List[int],target:int)->int:#左开右闭
left,right=0,len(nums)
while left < right:# 因为left == right的时候,在[left, right)是无效的空间,所以使用 <
middle=(left+right)//2
if nums[middle]>target:
right=middle
elif nums[middle]<target:
left=middle+1
else:
return middle
return -1
nums = [1, 2, 3, 4, 5, 6]
target_1 = 4
target_2 = 5
solution = Solution()
result_1= solution.search_1(nums, target_1)
result_2 = solution.search_1(nums, target_2)
if result_1!= -1:
print(f"目标值 {target_1} 在数组中的索引为 {result_1}")
else:
print(f"目标值 {target_1} 不在数组中")
if result_2!= -1:
print(f"目标值 {target_2} 在数组中的索引为 {result_2}")
else:
print(f"目标值 {target_2} 不在数组中")
总结:区间的定义就是不变量,那么在循环中坚持根据查找区间的定义来做边界处理,就是循环不变量规则。
类似题目练习:代码随想录
题目描述:. - 力扣(LeetCode)
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n)
的算法。
思路:刚开始选择了左闭右闭,但最后return了middle
题目一的python代码
区间左闭右闭
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left,right=0,len(nums)-1# 定义target在左闭右闭的区间里,[left, right]
while left<=right:
middle=(left+right)//2#返回商的整数部分
if nums[middle]<target:
left=middle+1
elif nums[middle]>target:
right=middle-1
else:
return middle
"""
// 分别处理如下四种情况
// 目标值在数组所有元素之前 [0, -1]
// 目标值等于数组中某一个元素 return middle;
// 目标值插入数组中的位置 [left, right],return right + 1
// 目标值在数组所有元素之后的情况 [left, right], 因为是右闭区间,所以 return right + 1
"""
return right+1
区间左闭右开
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left,right=0,len(nums)# 定义target在左闭右闭的区间里,[left, right)
while left<right:
middle=(left+right)//2#返回商的整数部分
if nums[middle]<target:
left=middle+1
elif nums[middle]>target:
right=middle
else:
return middle
"""
// 分别处理如下四种情况
// 目标值在数组所有元素之前 [0, 0)
// 目标值等于数组中某一个元素 return middle;
// 目标值插入数组中的位置 [left, right),return right
// 目标值在数组所有元素之后的情况 [left, right), 因为是右开区间,所以 return right
"""
return right
总结:比简单二分法多了插入位置的考虑,可以先假设数组中只有两个元素,得出在数组所有元素前的和在所有元素后的情况
其余情况类似
题目描述:. - 力扣(LeetCode)
给你一个按照非递减顺序排列的整数数组 nums
,和一个目标值 target
。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target
,返回 [-1, -1]
。
你必须设计并实现时间复杂度为 O(log n)
的算法解决此问题。
思路:不会,想着先用二分找到值,然后再看看是否有左右是否有与其相等的
示例 1:
输入:nums = [5,7,7,8,8,10]
, target = 8
输出:[3,4]
示例 2:
输入:nums = [5,7,7,8,8,10]
, target = 6
输出:[-1,-1]
示例 3:
输入:nums = [], target = 0 输出:[-1,-1]
题目二的python代码
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
def getRightBorder(nums: List[int], target: int) -> int:
left, right = 0, len(nums) - 1
rightneighbour = -2 # 未被赋值的情况
while left <= right:
middle = left + (right - left) // 2 # 防止溢出
if nums[middle] > target:
right = middle - 1
else:
left = middle + 1
rightneighbour = left
return rightneighbour
def getLeftBorder(nums: List[int], target: int) -> int:
left, right = 0, len(nums) - 1
leftneighbour = -2 # 未被赋值的情况
while left <= right:
middle = left + (right - left) // 2 # 防止溢出
if nums[middle] < target:
left = middle + 1
else:
right = middle - 1
leftneighbour = right
return leftneighbour
leftborder = getLeftBorder(nums, target)
rightborder = getRightBorder(nums, target)
if leftborder == -2 or rightborder == -2:#target大于或小于数组里元素的情况
return [-1, -1]
if rightborder - leftborder > 1:
return [leftborder + 1, rightborder - 1]
return [-1, -1]#target的值不大于或不小于数组里的元素,但在数组中没有
总结:先掌握一种写法,即分别找左边界和右边界(不含target),rightneighbour=-2的问题可举数组中只含有一个元素的情况,这是一个二分查找找边界的问题
二、27.移除元素
文档讲解:代码随想录
leetcode:. - 力扣(LeetCode)
python代码(暴力法)
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
i = 0
while i < len(nums):
if nums[i] == val:
nums.pop(i)
else:
i += 1
return len(nums)
python代码(双指针)
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
# 快慢指针
fast = 0 # 快指针
slow = 0 # 慢指针
size = len(nums)
while fast < size: # 不加等于是因为,a = size 时,nums[a] 会越界
# slow 用来收集不等于 val 的值,如果 fast 对应值不等于 val,则把它与 slow 替换
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
fast += 1
return slow
总结:408用过