1.二分查找
704.给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
适用:顺序数组,无重复
解题:循环查找,每次循环范围缩小一半
方法一:[left,right]
1、循环条件是left<=right, 因为是[4,4]是存在的
2、if target < nums[middle]: right = middle - 1,nums[middle]肯定不是target,直接进入左边区间找就行了
from typing import List
nums = [-1,0,3,5,9,12,15]
prompt="Please input a nummber you want to searh:"
target = input(prompt)
target = int(target)
def binary_search(nums: List[int],target: int):
left = 0
right = len(nums)-1
while left<=right:
middle = (left + right)//2
print("left:",left,"right",right,"middle:",middle)
if target < nums[middle]:
right = middle - 1
elif target > nums[middle]:
left = middle +1
else:
return middle
return -1
print("result:",binary_search(nums,target))
运行结果:
Please input a nummber you want to searh:9
left: 0 right 6 middle: 3
left: 4 right 6 middle: 5
left: 4 right 4 middle: 4
result: 4
方法二:[left,right)
1、循环条件是left<right,因为[4,4)没有意义
2、if target < nums[middle]: right = middle,这里没有减一是因为让它去左闭右开的区间里寻找,而且并不会找nums[middle]
from typing import List
nums = [-1,0,3,5,9,12,15]
prompt="Please input a nummber you want to searh:"
target = input(prompt)
target = int(target)
def binary_search(nums: List[int],target: int):
left = 0
right = len(nums)-1
while left < right:
middle = (left + right)//2
print("left:",left,"right",right,"middle:",middle)
if target < nums[middle]:
right = middle
elif target > nums[middle]:
left = middle +1
else:
return middle
return -1
print("result:",binary_search(nums,target))
运行结果:
Please input a nummber you want to searh:9
left: 0 right 6 middle: 3
left: 4 right 6 middle: 5
left: 4 right 5 middle: 4
result: 4
2.移除元素
27.给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
方法一:相向双指针
时间复杂度O(n)
空间复杂度O(1)
from typing import List
nums = [3,2,2,3]
def removeElement(nums: List[int],val: int):
if nums is None or len(nums)==0:
return 0
left = 0
right = len(nums)-1
while left < right :
while left<right and nums[left] != val:
left+=1 #找到前面等于val的数
while left<right and nums[right]==val:
right-=1 #找到后面不等于val的数
nums[left],nums[right] = nums[right],nums[left]
print(nums)
if nums[left]==val:
print(left)
return left
else:
print(left+1)
return left+1
removeElement(nums,3)
因为最后会在left=right时退出循环(并且多进行一次交换)如果此处的值为val,则最后一个数的下标是left-1,而返回的是数组长度,需要+1
[2, 2, 3, 3]
[2, 2, 3, 3]
2
方法二:快慢指针法
时间复杂度O(n)
空间复杂度O(1)
from typing import List
nums = [-1,0,3,3,9,3,15]
def removeElement(nums: List[int],val: int):
slowIndex ,fastIndex = 0,0
while fastIndex < len(nums):
if nums[fastIndex] != val:
if slowIndex != fastIndex: #加一个判断语句优化没必要的赋值
nums[slowIndex] = nums[fastIndex]
print(nums)
slowIndex+=1
fastIndex+=1
removeElement(nums,3)
运行结果:
[-1, 0, 9, 3, 9, 3, 15]
[-1, 0, 9, 15, 9, 3, 15]
3.有序数组的平方
977.给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1: 输
from typing import List
nums = [-10,-6,-4,-1,0,3,10,11,15]
def sortedSquares(nums: List[int]):
res=[]
left,right = 0,len(nums)-1
while left<=right :
if nums[left]>0 :
res.insert(0, nums[right] ** 2)
right-=1
elif -nums[left]<nums[right] :
res.insert(0, nums[right] ** 2)
right-=1
else:
res.insert(0, nums[left] ** 2)
left+=1
print(res)
return res
sortedSquares(nums)
运行结果:
[225]
[121, 225]
[100, 121, 225]
[100, 100, 121, 225]
[36, 100, 100, 121, 225]
[16, 36, 100, 100, 121, 225]
[9, 16, 36, 100, 100, 121, 225]
[1, 9, 16, 36, 100, 100, 121, 225]
[0, 1, 9, 16, 36, 100, 100, 121, 225]
4.长度最小的子数组
209.给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
滑动窗口解法
from typing import List
target = 4
nums = [1,4,4]
def minSubArrayLen(nums: List[int],target: int):
result = float("inf") #定义一个极大数
sum = 0 #滑动窗口的总和
subLength = 0 #滑动窗口的长度
i = 0 #滑动窗口的起始位置
j = 0 #滑动窗口的终止位置
while j < len(nums): #终止位置为j的最短窗口
sum += nums[j] #加入这个j的值
while sum >= target : #找到最短的窗口
subLength = j - i +1
if result > subLength:
result = subLength
sum = sum - nums[i] #再删除第一个窗口值
i+=1 #删除后起始位置移动
j+=1
if result > len(nums):
return 0
else:
return result
print(minSubArrayLen(nums,target))
5.螺旋矩阵II
59.给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
def generateMatrix(n:int):
nums = [[0] * n for _ in range(n)]
startx,starty = 0,0
loop = n//2
count = 1
for offset in range(1,loop+1):
for j in range(starty,n-offset):
nums[startx][j] = count
count+=1
for i in range(startx,n-offset):
nums[i][n-offset] =count
count+=1
for j in range(n-offset,starty,-1):
nums[n-offset][j] = count
count+=1
for i in range(n-offset,startx,-1):
nums[i][starty] = count
count+=1
startx+=1
starty+=1
if n%2 == 1:
nums[n//2][n//2] = count
return nums
nums=generateMatrix(5)
for i in range(len(nums)):
print(nums[i])
运行结果:
[1, 2, 3, 4, 5]
[16, 17, 18, 19, 6]
[15, 24, 25, 20, 7]
[14, 23, 22, 21, 8]
[13, 12, 11, 10, 9]