一、数组
本文章为数组的基础算法部分,相似题型汇总: 数组经典题型
1.1、二分查找
1.1.1、原题
力扣题目链接
二分查找的条件:
1.1.2、方法
根据区间的定义做边界处理。
想象有一个区间,该区间会随着二分而缩小范围,同时改变其左右闭边界([left, right])。不断二分该区间,比较mid与target的大小而选择二分区间其一。
def search(li, target):
left, right = 0, len(li)-1
while left<=right:
mid = (left+right)//2
if li[mid]>target:
right = mid-1
elif li[mid]<target:
left = mid +1
else:
return mid
return -1
注意这里每次划分都不包括mid的值。
1.1.3、相似题型
35.搜索插入位置 34.在排序数组中查找元素的第一个和最后一个位置 69.x的平方根 367.有效的完全平方数
1.2、双指针法
1.2.1、原题
力扣题目链接 元素的删除: 注意这里为原地操作,也就是原址操作。也就是在原列表的上进行的所有操作。 这里就要注意某些函数方法会产生新的地址,一般无返回值的函数为原址操作,有返回值的为新址操作: 比如: list.remove()无返回值,原址操作,改变原list,而不会产生新的list。 sorted(list)有返回值,新址操作,不改变原list,会产生新的list。
1.2.2、方法
1.一般解法,遍历一次列表: 思路:使用nums[:]创建一个新的list,遍历这个新的list,每次遇到val就删除原list等于val的值,这样就不会造成删除过程中index位移而错过连续的重复元素。
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
for i in nums[:]:
if i == val:
nums.remove(i)
return len(nums)
2.高级解法,快慢指针: 设定两个指针,快指针每次都往前移动一个索引,慢指针只有当快指针的值不等于val时,将它的值赋予给慢指针此刻的索引,再往后移动一格
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
fastIndex = 0
slowIndex = 0
while fastIndex <len(nums):
if nums[fastIndex]!=val:
nums[slowIndex] = nums[fastIndex]
slowIndex += 1
fastIndex += 1
return slowIndex
1.2.3、相似题型
26.删除排序数组中的重复项 283.移动零 844.比较含退格的字符串 977.有序数组的平方
1.3、滑动窗口
1.3.1、原题
力扣题目链接
1.3.2、方法
1.一般解法,暴力破解: 思路:因为是该子序列是连续的,所以定义起始点和结束点,以区间内的和和长度进行比较。因为是暴力求解,会遍历list,所以该解法遇到较长的list会超时。
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
lengt_h = float(inf)
for i in range(len(nums)):
su_m = 0
for j in range(i, len(nums)):
su_m = sum(nums[i:j+1])
if su_m>=target:
length = j-i+1
lengt_h = lengt_h if lengt_h<length else length
break
if lengt_h == 1:
break
return 0 if lengt_h == float(inf) else lengt_h
2.滑动窗口: 暴力破解定义了两个循环,分别代表了起始和结尾位置。 所以滑动窗口更加简化,只使用一个循环,动态维持一个起点到结尾的动态窗口,而这个循环表示结尾索引。
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
lengt_h = float(inf)
su_m = 0
ind = 0
for i in range(len(nums)):
su_m+=nums[i]
while su_m>=target:
lengt_h = min(lengt_h, i-ind+1)
su_m -= nums[ind]
ind += 1
return 0 if lengt_h == float(inf) else lengt_h
滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。
1.3.3、相似题型
904.水果成篮 76.最小覆盖子串
1.4、过程模拟
1.4.1、原题
力扣题目链接
1.4.2、方法
找规律,每一圈为一层,不断向内缩减
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
nums = [[0]*n for _ in range(n)]
startx, starty = 0, 0
loop, mid = n//2, n//2
count = 1
for offset in range(1, loop+1):
for i in range(starty, n-offset):
nums[startx][i] = count
count += 1
for i in range(startx, n-offset):
nums[i][n-offset] = count
count += 1
for i in range(n-offset, startx,-1):
nums[n-offset][i] = count
count += 1
for i in range(n-offset, starty, -1):
nums[i][starty] = count
count += 1
startx += 1
starty += 1
if n%2!=0:
nums[mid][mid] = count
return nums
1.4.3、相似题型
54.螺旋矩阵 剑指Offer 29.顺时针打印矩阵
参考
数组经典题型
|