66. 加一
给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
思路 1:
数组转为数字num计算num+1,然后在转为数组,时间空间复杂度都为O(n)
这种方法如果数字过大会溢出
(1)自己的做法:
class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
num=0
for i in digits:
num=10*num+i
num=num+1
result=[]
while(num!=0):
result.append(num%10)
num=num//10
return result[::-1]
(2)使用join str list方法直接完成数字与list之间的转换
class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
return [int(x) for x in list(str(int("".join([str(i) for i in digits]))+1))]
思路 2:
list最后一位加1,然后检查list中是否含有大于10的元素,对于大于十的元素-10,前一位+1,list[0]考虑需不需要在首位+1,时间复杂度O(n),空间复杂度O(1)
class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
digits[-1]+=1
for i in range(1,len(digits)):
if digits[-i]>=10:
digits[-i]-=10
digits[-i-1]+=1
if digits[0]>=10:
digits[0]-=10
digits.insert(0,1)
return digits
724. 寻找数组的中心下标
用sum会超时,用滑窗
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
left=0
right=sum(nums[1:])
index=-1
if sum(nums[:-1])==0:
index=len(nums)-1
for i in range(len(nums)-1):
if left==right:
index=i
break
left+=nums[i]
right-=nums[i+1]
return index
189.轮转数组
给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
用python切片直接拼接
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n=k%len(nums)
nums[:]=nums[-n:]+nums[:-n]
注意:用nums[:]不会开辟新内存
48.旋转图像
给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
先转置,然后对每一行反转
#python创建二维数组时不能 matrix_new = matrix 或 matrix_new = matrix[:] 因为是引用拷贝
需要matrix_new = [[0] * n for _ in range(n)]
class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
for i in range(len(matrix)):
for j in range(i+1,len(matrix)):
temp=matrix[i][j]
matrix[i][j]=matrix[j][i]
matrix[j][i]=temp
for L in matrix:
L.reverse()
官方解答:
class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
n = len(matrix)
# 水平翻转
for i in range(n // 2):
for j in range(n):
matrix[i][j], matrix[n - i - 1][j] = matrix[n - i - 1][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]
54.螺旋矩阵
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
思路:
只会按照右下左上的方向遍历,将已经遍历过的值取None,如果碰到矩阵边界或取到None值则改变方向,当需返回的list长度等于原矩阵元素数时break
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
m,n=len(matrix),len(matrix[0])
#flag=0,1,2,3表示向右下左上前进
flag=0
i,j=0,0
result=[]
while(1):
if matrix[i][j]!=None:
result.append(matrix[i][j])
#将已经遍历过的值取None
matrix[i][j]=None
if len(result)==m*n:
break
if flag==4:
flag=0
if flag==0:
#碰到边界或已经遍历过的值,改变方向,只会按右下左上的方向取值
if j+1==n or matrix[i][j+1]==None:
flag+=1
else:
j+=1
if flag==1:
if i+1==m or matrix[i+1][j]==None:
flag+=1
else:
i+=1
if flag==2:
if j==0 or matrix[i][j-1]==None:
flag+=1
else:
j-=1
if flag==3:
#向上走不会碰到边界,只会碰到已遍历的值
if matrix[i-1][j]==None:
flag+=1
else:
i-=1
return result
改进版代码
确定上下左右四个边界,每次取完一行或一列的值,缩小边界
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
top,bottom,left,right=0,len(matrix)-1,0,len(matrix[0])-1
L=[]
while(1):
for i in range(left,right+1):
L.append(matrix[top][i])
top+=1
if top>bottom:break
for i in range(top,bottom+1):
L.append(matrix[i][right])
right-=1
if left>right:break
for i in range(right,left-1,-1):
L.append(matrix[bottom][i])
bottom-=1
if top>bottom:break
for i in range(bottom,top-1,-1):
L.append(matrix[i][left])
left+=1
if left>right:break
return L
思路2:
每次取首行,取完后去掉首行,翻转矩阵,至原矩阵为[]
class Solution(object):
def spiralOrder(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: List[int]
"""
# 取首行,去除首行后,对矩阵翻转来创建新的矩阵,
# 再递归直到新矩阵为[],退出并将取到的数据返回
ret = []
if matrix == []:
return ret
ret.extend(matrix[0]) # 上侧
new = [reversed(i) for i in matrix[1:]]
if new == []:
return ret
r = self.spiralOrder([i for i in zip(*new)])
ret.extend(r)
return ret
498.对角线遍历
给你一个大小为 m x n 的矩阵 mat ,请以对角线遍历的顺序,用一个数组返回这个矩阵中的所有元素。
思路:
首先顺序遍历所有对角线(共m+n-1)条,序数为奇数的对角线需要倒序
class Solution:
def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
m,n=len(mat),len(mat[0])
L=[]
num=0#记录对角线序数
#第一行元素对应的对角线
for j in range(n):
i=0
temp=[]
while(1):
if i==m or j<0:
num+=1
break
temp.append(mat[i][j])
i+=1
j-=1
if num%2==1:
temp.reverse()
L.extend(temp)
#最后一列元素对应的对角线
for i in range(1,m):
j=n-1
temp=[]
while(1):
if i==m or j<0:
num+=1
break
temp.append(mat[i][j])
i+=1
j-=1
if num%2==1:
temp.reverse()
L.extend(temp)
return L