《LeetCode零基础指南》(第七讲) 二维数组
思路:暴力拆解一个个遍历,判断负数的数量
解法一:两个for循环查找,时间复杂度为O(n*m)
class Solution:
def countNegatives(self, grid: List[List[int]]) -> int:
count=0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j]<0:
count+=1
return count
解法二:代码简便化,时间复杂度没有改变,仍然是O(n*m)
class Solution:
def countNegatives(self, grid: List[List[int]]) -> int:
return sum(x<0 for j in grid for x in j)
解法三:二分查找。优化的二分查找,对于每一行的数据根据单调性我们可以采用二分查找的思路求解,迅速滑动到第一个负数的位置,降低时间复杂度,这里我们优化一下二分查找,因为每一列的数据也是单调的,所以下一行的righ tright指针的初始值可以设置为上一次的结束位置,这样就充分利用了行和列的单调性,进一步提升二分查找的速度。时间复杂度是O(n*logm)
class Solution:
def countNegatives(self, grid: List[List[int]]) -> int:
m, n = len(grid[0]),len(grid)
res,ind = 0,m
for i in range(n):
if ind==0: break
if grid[i][ind-1]>=0: continue
left, right= 0, ind
while left<right:
mid = left+(right-left)//2
if grid[i][mid]>=0: left = mid + 1 # 二分的思想,查找到负数的位置
else: right = mid
res += (ind-left)*(n-i)
ind = left
return res
第四种解法:指针搜索法。指针,每一行和每一列的元素都是单调的,那么我们可以定义一个列指针ind ind,先从第一行最后往前滑动,移到第一个负数的索引ind ind位置,由单调性可知,其下面和右面的所有元素都小于0,因此累加结果res=res+(m-ind)*n res=res+(m−ind)∗n,其中m,n分别对应矩阵的列和行数。时间复杂度是O(m)。
class Solution:
def countNegatives(self, grid: List[List[int]]) -> int:
m, n = len(grid[0]),len(grid) # 确定二维列表的列和行的数目
res,ind = 0,m # res计数
for i in range(n): # 循环开始
if ind==0: break
if grid[i][ind-1]>=0: continue # 如果每一行的最后一个数都大于0,则代表前面所有的数都大于零,则换行
cnt = 0;
while ind-1>=0 and grid[i][ind-1]<0: # 在一个个排查,如果出现数组中的数小于零
ind -= 1
cnt += 1 # 则直接计算那一行的位置
res += cnt*(n-i) # 计算叠加多少个负数
return res
思路:暴力解法,根据行和列的关系进行求解
解法一:两个for循环遍历,暴力拆解,时间复杂度是O(n*n)
class Solution:
def diagonalSum(self, mat: List[List[int]]) -> int:
n=len(mat)
sum=0
for i in range(n):
for j in range(n):
if i==j or i+j==(n-1):
sum+=mat[i][j]
return sum
解法二:逐行遍历,记当前的行号为 ii,对于一行我们把 (i, i)(i,i) 位置和 (i, n - i - 1)(i,n−i−1) 加入答案。这样如果 nn 是奇数的话,最中间的格子会被加入两次。所以 nn 为奇数的时候,我们需要减掉矩阵最中心的那个值。时间复杂度:O(n)。
class Solution:
def diagonalSum(self, mat: List[List[int]]) -> int:
n = len(mat)
total = 0
mid = n // 2
for i in range(n):
total += mat[i][i] + mat[i][n - 1 - i]
return total - mat[mid][mid] * (n & 1) # 通过按位运算进行判断是否需要剪掉中间重复的数字
思路:暴力找到每行的和的最大值
解法一:for循环,遍历每一列,然后求和比较大小。时间复杂度O(n)
class Solution:
def maximumWealth(self, accounts: List[List[int]]) -> int:
s=0
for i in range(len(accounts)):
t=max(s,sum(accounts[i]))
s=t
return s
解法二:代码的优化,时间复杂度没有实质性的改变。时间复杂度是O(n)。
class Solution:
def maximumWealth(self, accounts: List[List[int]]) -> int:
return max(sum(accounts[i]) for i in range(len(accounts)))
思路:这道题规律性很强,类似第一行的数右移,然后在第一个数前面添加一个数。
解法:for循环每一行,if判断是否满足所需的要求,最后输入结果。时间复杂度为O(n)
class Solution:
def isToeplitzMatrix(self, matrix: List[List[int]]) -> bool:
for i in range(len(matrix) - 1):
if matrix[i][:-1] ! = matrix[i + 1][1:]:
return False
return True

浙公网安备 33010602011771号