提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
记录算法学习的第一天
一、LeetCode 704-二分查找
给定一个 n
个元素有序的(升序)整型数组 nums
和一个目标值 target
,写一个函数搜索 nums
中的 target
,如果目标值存在返回下标,否则返回 -1
。
示例 1:
输入:nums= [-1,0,3,5,9,12],
target= 9
输出: 4 解释: 9 出现在nums中并且下标为 4 题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/
二分法概念:首先我们要先明白二分法有几部分构成 它由三部分 左区间 右区间 middle构成 我们就是(左区间+右区间)/2然后得出middle 再和target相对比看看target是在middle左边还是右边 在左边就是right=middle-1 在右边我们就left=middle+1 最后求到最后left=right时就是我们target的下标
解题思路:我们常见思路就是两种方法 一种是左闭右闭 一种是左闭右开
1.左闭右闭写法[left,right]
class Solution:
def search(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums)-1
while left<=right:
middle = left+(right-left) // 2
if nums[middle] > target:
right = middle-1
elif nums[middle] < target:
left = middle+1
else :
return middle
return -1
2.左闭右开写法[left,right)
class Solution:
def search(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums)
while left < right:
middle = left + (right - left) // 2 #这里不要(left+****)//2会超时
if nums[middle] > target:
right = middle
elif nums[middle] < target:
left = middle + 1
else:
return middle
return -1
3.难点
1.right的确定
- 左闭右闭区间[left,right]
nums= [-1,0,3,5,9,12]它从头到尾遍历6次所以我们可以确定left=0,right=5 也就是 right=len(nums)-1
right在左闭右闭中可以为middle-1 假设target为3那么就是说可以右区间移动就可以说 middle-1变成[-1,0,3] 3是可以取得到的所以left的+1 right-1都无所谓了
``左闭右开区间[left,right)
nums= [-1,0,3,5,9,12]它从头到尾遍历6次所以我们可以确定left=0,但是这里的 right我们取不到所以我们的right要为6也就是right=len(nums)
- right在左闭右开的区间中如果说target就正好紧接着middle的左边那就middle-1就可能取不 到了 所以就需要right=middle
2.middle的确定
-
mid = (right - left) // 2
这种写法运用在这里根本就是错误的。因为right - left 仅仅代表两者之间相差几个数的距离,再除以2只是说从左到右的一半距离,和下标就没有关系了。 -
mid = (right + left) // 2
这种写法会发生上溢问题。int 占用 4 字节,32 比特,数据范围为:-2147483648 ~ 2147483647
[-2^31 ~ 2^31-1]
那么对于两个都接近
2147483647
的数字而言,它们相加的结果将会溢出,变成负数。所以,为了避免溢出情况的发生,我们不采用这种写法。 -
mid = left + (right - left) // 2
从左指针到右指针的一半距离 + 左指针的下标 才是符合题的下标位置。
总结
在写二分法时经常要注意区间的问题 左闭右闭 左闭右开的情况然后就是确定right怎么写左闭右开就是middle 左闭右闭middle-1 然后就是middle的确定
二、LeetCode 27-移除元素
题目描述:给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素,并返回移除后数组的新长度。
题目描述
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1)
额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
-
暴力解法
#暴力解法
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
i=0
l=len(nums)
while i<l:
if nums[i] == val:
for j in range(i+1,l):
nums[j - 1] = nums[j]
l -=1
i -=1
i +=1
return l
-
双指针解法
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
slow=0 #慢指针
fast=0 #快指针
for fast in range(fast,len(nums)):
if nums[fast]!=val:
nums[slow]=nums[fast]
slow += 1
fast +=1
return slow
- 解题思路
定义两个指针 一个快指针来遍历原来数组寻找需要的元素 一个慢指针在后面跟着更新的数组 这样就可以用一个for循环完成 时间复杂度为O(n)
- 难点
经常容易第一反应是暴力解法 双指针解法会是更优解
-
总结
双指针解法经常用在数组和链表当中要多多练习
总结
前路漫漫 脚踏实地的走吧