总体规划
目前基础:力扣hot100已刷73题,dp相关的目前还没涉及
困难:解题思路不清晰,非常依赖题解,且对考点(数据结构)不是很确定
总体目标🎯:
- 通过《代码随时想录》的分类,比较完善的查漏补缺的刷一遍
- 力抓简单+中等,难题适当做
- 先保质再保量
每日目标:
- 完成两道编程题
Part 1、数组
概念
- 数组是存放在连续内存空间上的相同类型数据的集合。
- 读取方便,读取时时间复杂度为O(1)
- 删除或者增加数据的时候,需要移动一定范围的元素,时间复杂度为O(n)
- 数组不能删除,只能覆盖
1.二分查找
题目描述
考点
为啥能用二分查找?
- 关键词:有序
- 关键词:不重复
考你啥?
- 边界的处理,left,right是开还是闭
要点
为什么用mid=(right-left)//2 +left,不用mid=(right+left)//2?
——当left和right很大的时候,可以起到防止溢出的作用
完整代码
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
left, right = 0, len(nums)-1
while left <= right:
# mid = (left + right) // 2
mid = (right - left) //2 + left
if nums[mid] < target:
left = mid +1
elif nums[mid] >target:
right = mid - 1
else:
return mid
return -1
时间复杂度:O(logn)
空间复杂度:O(1)
2.移除元素
题目描述
考点
- 数组无法删除,只能进行覆盖
要点
- 数组下标越界的细节掌握
完整代码
解法一:暴力法
思路:双层循环,进行覆盖,记录等于val值的数量,最后返回数组长度减去val值个数,即为删除指定元素后的长度
class Solution(object):
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
#逆序查找
n=len(nums)
count = 0
for i in range(n-1, -1, -1):
if nums[i] == val:
count += 1
for j in range(i, n-1):
nums[j]=nums[j+1]
nums[n-1]=0
return n-count
时间复杂度:O(n^2)
空间复杂度:O(1)
解法二:快慢指针(代优化)
3.有序数组的平方
题目描述
考点
- 双指针
要点
- while循环语句中left是小于等于right,因为两者相遇的时候的值即为最小值,也需要存入结果中
解法一:暴力法
直接平方后进行排序
class Solution(object):
def sortedSquares(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
for i in range(len(nums)):
nums[i] = nums[i] ** 2
return sorted(nums)
时间复杂度:O(n+nlogn)=O(nlogn)
空间复杂度:O(1)
解法二:双指针
思路:定义左右指针left和right,分别指向头部和尾部,再定义一个存放结果的res,比较左右指针绝对值更大的数,将其存放在res的尾部,然后将绝对值更大的数所对应的指针向中间移动,直到两指针相遇,即存放完毕。
class Solution(object):
def sortedSquares(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
#双指针
#一头一尾,找更大的值,逆序存入数组中
left , right = 0 , len(nums) - 1
res = [0] * len(nums)
i = len(nums) - 1
while left <= right:
if abs(nums[left]) <= abs(nums[right]):
res[i] = nums[right] ** 2
right -= 1
else:
res[i] = nums[left] ** 2
left += 1
i -= 1
return res
时间复杂度:O(n)
空间复杂度:O(n)
4.长度最小的子数组(需二刷)
题目描述
考点
- 滑动窗口的灵活使用
要点
- 第一个while用来锁定判断区间的截止位置
- 第二个while循环用来判断当前子串是否符合条件,若符合,则计算当前子串长度,并更新当前子串和,移动左指针
- 此次对于两个while循环的逻辑已经不清晰了,下次要注意抓出判断条件
解法一:暴力法(双层for循环O(n^2),会报错,超出时间限制)
解法二:滑动窗口
class Solution(object):
def minSubArrayLen(self, target, nums):
"""
:type target: int
:type nums: List[int]
:rtype: int
"""
#滑动窗口
left , right = 0 , 0
res = float('inf')
cur_sum=0
n = len(nums)
while right < n :
cur_sum += nums[right]
while cur_sum >= target:
res = min(res , right - left +1)
cur_sum -= nums[left]
left += 1
right += 1
return res if res!=float('inf') else 0
时间复杂度:O(n) 虽然有两个while循环,但是left和right都是向右侧移动,没有回退吗所以时间复杂度是O(n)
空间复杂度:O(1)