《LeetCode零基础指南》(第七讲) 二维数组

1351. 统计有序矩阵中的负数 - 力扣(LeetCode) (leetcode-cn.com)

思路:暴力拆解一个个遍历,判断负数的数量

解法一:两个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

1572. 矩阵对角线元素的和 - 力扣(LeetCode) (leetcode-cn.com)

思路:暴力解法,根据行和列的关系进行求解

解法一:两个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) # 通过按位运算进行判断是否需要剪掉中间重复的数字

1672. 最富有客户的资产总量 - 力扣(LeetCode) (leetcode-cn.com)

思路:暴力找到每行的和的最大值

解法一: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)))

766. 托普利茨矩阵 - 力扣(LeetCode) (leetcode-cn.com)

思路:这道题规律性很强,类似第一行的数右移,然后在第一个数前面添加一个数。

解法: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

 

posted @ 2022-04-03 23:01  食尸之鬼  阅读(41)  评论(0)    收藏  举报