日常系列LeetCode《3·二维数组篇》

Posted 常某某的好奇心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日常系列LeetCode《3·二维数组篇》相关的知识,希望对你有一定的参考价值。

数据规模->时间复杂度

<=10^4 😮(n^2)
<=10^7:o(nlogn)
<=10^8:o(n)
10^8<=:o(1)

总结:
1.索引计算:根据某个元素的行列索引计算另一个元素的行列索引
2.行走遍历:在二维数组中行走遍历
3.元素值计算:根据二维数组某些元素计算另一个元素值

lc 867:https://leetcode.cn/problems/transpose-matrix/
提示:
m = =matrix.length
n = =matrix[i].length
1 <= m, n <= 1000
1 <= m * n <= 10^5
-10^9 <= matrix[i][j] <= 10^9

class Solution:
    def transpose(self, matrix: List[List[int]]) -> List[List[int]]:
        #o(m*n)
        m,n=len(matrix),len(matrix[0])
        t=[[0]*m for i in range(n)]
        #
        for i in range(m):
            for j in range(n):
                t[j][i]=matrix[i][j]
        #
        return t

lc 48 【top100】:https://leetcode.cn/problems/rotate-image/
提示:
n = = matrix.length = = matrix[i].length
1 <= n <= 20
-1000 <= matrix[i][j] <= 1000

方案一(不满足):使用额外数组(o(n^2),o(n^2)#对于矩阵中第row行的第col列元素,在旋转后,它出现在倒数第row列的第col行位置。
方案二:原地旋转
class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        #o(1)
        n=len(matrix)
        #o(n^2)
        for i in range(n//2): #取整3.5-3,4.0-4.5
            for j in range((n+1)//2):
                #留空
                tmp=matrix[i][j]
                #
                matrix[i][j]=matrix[n-1-j][i]
                matrix[n-1-j][i]=matrix[n-1-i][n-1-j]
                matrix[n-1-i][n-1-j]=matrix[j][n-1-i]
                matrix[j][n-1-i]=tmp
        #
        return matrix
        
方案三:原地翻转:水平翻转->主对角线翻转
class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        #o(1)
        n=len(matrix)
        #o(n^2)
        #水平交换
        for i in range(n//2): 
            for j in range(n):
                matrix[i][j],matrix[n-1-i][j]=matrix[n-1-i][j], matrix[i][j]
        #主对角线转置
        for i in range(n):
            for j in range(i):
                matrix[i][j],matrix[j][i]=matrix[j][i], matrix[i][j]
        #
        return matrix

lc 36:https://leetcode.cn/problems/valid-sudoku/
提示:
board.length = = 9
board[i].length == 9
board[i][j] 是一位数字(1-9)或者 ‘.’

#rowUsed[row][num] = true:在数字num + 1在row行已经存在
#colUsed[col][num] = true:在数字num + 1在col行已经存在
#boxUsed[boxIndex][num] = true:在数字num + 1在boxIndex个箱子已经存在
class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        #o(n)
        rowused=[[False]*9 for _ in range(9)]
        colused=[[False]*9 for _ in range(9)]
        boxused=[[False]*9 for _ in range(9)]
        #o(n^2)
        for i in range(9):
            for j in range(9):
                if board[i][j]!='.':
                    num=ord(board[i][j])-ord('1')
                    #
                    if rowused[i][num]:return False
                    else:rowused[i][num]=True
                    if colused[j][num]:return False
                    else:colused[j][num]=True
                    if boxused[(i//3+(j//3)*3)][num]:return False
                    else:boxused[(i//3+(j//3)*3)][num]=True
        #
        return True

lc 73 :https://leetcode.cn/problems/set-matrix-zeroes/
提示:
m = = matrix.length
n == matrix[0].length
1 <= m, n <= 200
-2^31 <= matrix[i][j] <= 2^31 - 1
进阶:
一个直观的解决方案是使用 O(mn) 的额外空间,但这并不是一个好的解决方案。
一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。
你能想出一个仅使用常量空间的解决方案吗?

#方案一:o(m*n):一个矩阵
#方案二:o(m+n):两个数组
#记录每行是否需要置为О;记录每列是否需要置为0
class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        #o(m+n)
        rows=[False]*len(matrix)
        cols=[False]*len(matrix[0])
        #o(m*n)
        #标记
        for i in range(len(matrix)):
            for j in range(len(matrix[0])):
                if matrix[i][j]==0:
                    rows[i]=True
                    cols[j]=True
        #设0
        for i in range(len(matrix)):
            for j in range(len(matrix[0])):
                if rows[i] or cols[j]:
                    matrix[i][j]=0
        #
        return matrix
        
#方案三:o(1):单数组
#核心:'第一列是否含0'作为整体标记,方便了处本列之外信息的设0
#注:为了防止每一列的第一个元素被提前更新,我们需要从最后一行开始,倒序地处理矩阵元素
class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        #o(1)
        m=len(matrix)
        n=len(matrix[0])
        #o(n)
        #标记
        col1=False       
        
        for i in range(m):
            if matrix[i][0]==0:#第一列(是否含0)
                col1=True
            for j in range(1,n):
                if matrix[i][j]==0:#其他行、列(含0信息)
                    matrix[i][0]=matrix[0][j]=0
        #设0
        for i in range(m-1,-1,-1): #注:逆序
            for j in range(1,n):
                if matrix[i][0]==0 or matrix[0][j]==0:
                    matrix[i][j]=0  
            if col1:#注:放最后
                matrix[i][0]=0    
        #
        return matrix

#核心:'第一行是否含0'作为整体标记,方便了处本行之外信息的设0
#注:为了防止每一行的第一个元素被提前更新,我们需要从最后一列开始,倒序地处理矩阵元素
class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        #o(1)
        m=len(matrix)
        n=len(matrix[0])
        #o(n)
        #标记
        row1=False

        for j in range(n):
            if matrix[0][j]==0:#第一行(是否含0)
                row1=True       
        
        for i in range(1,m):
            for j in range(n):
                if matrix[i][j]==0:#其他行、列(含0信息)
                    matrix[i][0]=matrix[0][j]=0

        #设0
        for i in range(1,m): 
            for j in range(n-1,-1,-1):#注:逆序
                if matrix[i][0]==0 or matrix[0][j]==0:
                    matrix[i][j]=0  
        
        for j in range(n):            
            if row1:#注:放最后
                matrix[0][j]=0    
        #
        return matrix

lc 54 【 剑指 29】:https://leetcode.cn/problems/spiral-matrix/
提示:
m = = matrix.length
n == matrix[i].length
1 <= m, n <= 10
-100 <= matrix[i][j] <= 100

#方案一:直接模拟
class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        #o(m*n)
        m,n=len(matrix),len(matrix[0])
        dirs=[[0,1],[1,0],[0,-1],[-1,0]]
        seen=[[False]*n for _ in range(m)] #m行n列
        res=[]
        #o(m*n)
        i,j=0,0
        di=0
        for s in range(m*n):
            res.append(matrix[i][j])
            seen[i][j]=True
            #变换条件
            next_i=i+dirs[di][0]
            next_j=j+dirs[di][1]
            if next_i<0 or next_i>=m or next_j<0 or next_j>=n or seen[next_i][next_j]:
                di=(di+1)%4 #注
            #更新
            i=i+dirs[di][0]
            j=j+dirs[di][1]
        #
        return res
 #方案二:按层模拟
  #o(1)
class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        start_row=start_col=0
        end_row,end_col=len(matrix)-1,len(matrix[0])-1 #注意写法
        res=[]
        #o(m*n)
        #注意下标
        while start_row<=end_row and start_col<=end_col:
            for col in range(start_col,end_col+1):res.append(matrix[start_row][col])
            for row in range(start_row+1,end_row+1):res.append(matrix[row][end_col])
            #注:边界(单行、单列)
            if start_row<end_row and start_col<end_col:
                for col in range(end_col-1,start_col,-1):res.append(matrix[end_row][col])
                for row in range(end_row,start_row,-1):res.append(matrix[row][start_col])
            #
            start_col+=1
            start_row+=1
            end_col-=1
            end_row-=1 
        return res

lc 59 :https://leetcode.cn/problems/spiral-matrix-ii/
提示:
1 <= n <= 20

#方案一:直接模拟
class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        #o(1)
        dirs=[[0,1],[1,0],[0,-1],[-1,0]]
        seen=[[False]*n for _ in range(n)]
        res=[[0]*n for _ in range(n)]
        #o(m*n)
        i,j=0,0
        di=0
        for s in range(n*n):
            res[i][j]= s+1
            seen[i][j]=True
            #变换条件
            next_i=i+dirs[di][0]
            next_j=j+dirs[di][1]
            if next_i<0 or next_i>=n or next_j<0 or next_j>=n or seen[next_i][next_j]:
                di=(di+1)%4 #注
            #更新
            i=i+dirs[di][0]
            j=j+dirs[di][1]
        #
        return res
        
 #方案二:按层模拟
class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        #o(1)
        start_row=start_col=0
        end_row,end_col=n-1,n-1 #注意写法
        res=[[0]*n for _ in range(n)]
        #o(m*n)
        #注意下标
        i=0
        while start_row<=end_row and start_col<=end_col:
            for col in range(start_col,end_col+1):
                res[start_row][col]=i+1
                i+=1
            for row in range(start_row+1,end_row+1):
                res[row][end_col]=i+1
                i以上是关于日常系列LeetCode《3·二维数组篇》的主要内容,如果未能解决你的问题,请参考以下文章

日常系列LeetCode《1·数组常用技巧篇》

Leetcode篇:旋转图像

日常系列LeetCode《9·哈希查找篇》

日常系列LeetCode《8·二分查找篇》

日常系列LeetCode《5·数学篇》

LeetCode系列-Remove Duplicates from Sorted Array II