04. 二维数组中的查找
方法一:暴力遍历
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
for lst in matrix:
if target in lst:
return True
return False
时间复杂度是 O ( M N ) O(MN) O(MN), M M M和 N N N分别是数组的行数与列数。
方法二:二叉搜索树
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
i, j = len(matrix) - 1, 0
while i >= 0 and j < len(matrix[0]):
if matrix[i][j] > target: i -= 1
elif matrix[i][j] < target: j += 1
else: return True
return False
- 复杂度分析
- 时间复杂度 O ( M + N ) O(M+N) O(M+N):其中, N N N和 M M M分别为矩阵行数和列数,此算法最多循环 M + N M+N M+N次。
- 空间复杂度 O ( 1 ) O(1) O(1): i i i, j j j指针使用常数大小额外空间
59. 滑动窗口的最大值
方法一:暴力法
按照索引递增,逐个窗口找最大值
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
result = []
if nums == []:
return []
for i in range(0, len(nums) - k + 1):
result.append(max(nums[i : i + k]))
return result
方法二:单调队列
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
if not nums or k == 0: return [] # 如果列表本身为空
deque = collections.deque() # 初始化单调队列
for i in range(k): # 未形成窗口
while deque and deque[-1] < nums[i]: # 如果队列里的最大值([-1]位置上)小于新加入的值,弹出队列末尾的值
deque.pop()
deque.append(nums[i])
res = [deque[0]] # 压入第一个滑窗里的最大值
for i in range(k, len(nums)): # 形成窗口后
if deque[0] == nums[i - k]:
deque.popleft() # 滑窗移动,原始滑窗的第一个数被排除
while deque and deque[-1] < nums[i]: # 弹出滑窗里没有新数字大的部分
deque.pop()
deque.append(nums[i])
res.append(deque[0])
return res
- 复杂度分析:
- 时间复杂度 O ( n ) O(n) O(n):其中 n n n为数组 n u m s nums nums长度,线性遍历数组占用 O ( N ) O(N) O(N),每个元素最多仅入队和出队一次,因此单调队列占用 O ( 2 N ) O(2N) O(2N)的时间
- 空间复杂度 O ( k ) O(k) O(k):双端队列 d e q u e deque deque中最多同时存储 k k k个元素(即窗口大小)