四月份还是三月份有蓝桥杯的算法比赛,加上一直对算法感兴趣。所以从现在开始稍微学一下。
每天会坚持做几题吧,因为不知道哪些比较重要,我就主要记一些我认为重要的内容和算法
数组
数组中心索引
数组和字符串 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台
当数组中一个索引右边的和等于左边和时,称这个索引为数组的中心索引
def midIndex(nums:List[int])->int:
all = sum(nums)
left = 0
for i in range(len(nums)):
if left*2+nums[i]==all:
return i
else:
left += nums[i]
return -1
大概的思路就是根据它的数值对称的思路来实现中心索引的寻找
二分法查找
数组和字符串 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台
这是一个经典的查找算法,相较于线性查找,它的时间复杂度更简单O(log_n)
def binary_search(nums:List[int],target:int)->int:
left,right = 0,len(nums)-1
while left<=right:
mid = left + (right-left)//2 # 避免整数溢出
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid+1
else:
right = mid-1
return -1
首先设置左右边界,然后判断目标在左区间还是右区间。如果在左区间,则更改右边界条件;在右区间,则更改左边界条件。直到找到目标数值,返回索引
区间合并
数组和字符串 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台
给一个若干区间组成的数组,其区间含义为[start,end],我们将其进行合并
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort(key= lambda x:x[0])
rList = list()
for interval in intervals:
if not rList or rList[-1][-1]<interval[0]:
rList.append(interval)
else:
rList[-1][-1] = max(rList[-1][-1],interval[1])
return rList
首先根据区间的起始位置进行排序,然后创建一个新的列表,设置以下规则:
- 当列表为空时,加入数组
- 当列表中数组的最后一位小于当前数组的第一位,说明不重叠,加入数组
- 当发生重叠时,比较两数组的最后一位,保留大的数字
二维数组
旋转矩阵
数组和字符串 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台
给你一个NXN矩阵表示的图像,其中每个像素大小为4字节,设计一种算法,将图像顺时针旋转90°
方法一:
使用一个额外的数组来辅助完成
def rotate(self,matrix: List[List[int]])->List[List[int]]:
rlists = list()
for j in range(len(matrix[0])):
rlist = list()
for i in range(len(matrix)-1,-1,-1):
rlist.append(matrix[i][j])
rlists.append(rlist)
return rlists
这个实际上是通过更改读取顺序的方式,重新创建一个矩阵,但是不符合题目不额外使用空间的思想
方法二:
通过矩阵的几何特性来实现
def rotate(self,matrix: List[List[int]]):
N = len(matrix)
# 对角线互换
for i in range(N):
for j in range(i): # 这里要仔细理解,因为接下来要进行互换,所以j要随i增大
matrix[i][j],matrix[j][i] = matrix[j][i],matrix[i][j]
# 水平互换
for i in range(N):
matrix[i][:] = matrix[i][::-1]
这里我们可以总结:
- 顺时针旋转90°,先对角翻转,再水平翻转
- 逆时针旋转90°,先水平翻转,再对角线翻转
零矩阵
数组和字符串 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台
数字0所在的行与列,在矩阵中全部置0
def setZeroes(self, matrix:List[List[int]]):
M=len(matrix)
N=len(matrix[0])
line=[0]*M
row=[0]*N
for i in range(M):
for j in range(N):
if matrix[i][j]==0:
line[i] = 1
row[j] = 1
for i in range(M):
for j in range(N):
if line[i]==1 or row[j]==1:
matrix[i][j]=0
这个方法很直观,分别创建行和列的索引,并进行标记,当匹配到标记时,将数据置0
对角线遍历
数组和字符串 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台
给你一个大小mxn的矩阵mat,以对角线遍历的顺序,用一个数组返回
class Solution(object):
def findDiagonalOrder(self, mat:List[List[int]])->List[int]:
ans = []
Xsize = len(mat)
Ysize = len(mat[0])
tot = Xsize + Ysize - 1
x,y = 0,0
for i in range(tot):
if i%2==1:
while y>=0 and x<Xsize:
ans.append (mat[x][y])
x += 1
y -= 1
if x<Xsize:
y += 1
else:
y += 2
x -= 1
else:
while x>=0 and y<Ysize:
ans.append (mat[x][y])
x -= 1
y += 1
if y<Ysize:
x += 1
else:
x += 2
y -= 1
return ans
这道题目难在边界条件的处理,需要仔细分析(分类讨论)
**注意:**在观察二维数组时,一定要把索引与行列之间的关系理清除
这里附上一个很好的解答498. 对角线遍历 - 力扣(LeetCode)