剑指 Offer 数组类
#暴力
for row in matrix:
if target in row:
return True
return False
从右上角开始,如果Target比右上角大则舍弃第一行,若比右上角小舍弃最后一列。
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
if len(matrix)==0 or len(matrix[0])==0:
return False
rows=len(matrix)-1
x=0
y=len(matrix[0])-1
while(rows>=x and y>=0):
corner=matrix[x][y]
if(target>corner):
x=x+1
elif(target<corner):
y=y-1
elif(target==corner):
return True
return False
从左下角开始的版本,似乎用时比右上角少点
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
if len(matrix)==0 or len(matrix[0])==0:
return False
rows=len(matrix)-1
x=rows
cols=len(matrix[0])-1
y=0
while(x>=0 and y<=cols):
corner=matrix[x][y]
if(target>corner):
y=y+1
elif(target<corner):
x=x-1
elif(target==corner):
return True
return False
####################################################
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
n=len(nums)
for index in range(0,n):
while(index !=nums[index]):
temp=nums[index]
temp2=nums[temp]
if(temp2==temp):
return temp
nums[index],nums[temp]=nums[temp],nums[index]
###################################################
俺只想说简单题都这样,俺还是继续回去当保安吧。
最开始自己写尝试写了向上 向下 向左 向右四个函数,想法是从左上角开始在一个while循环中依次调用四个函数;然而边界一直处理不好,只能通过一半的测试用例。
索性还是直接看解析了。解析第一个解法 通过维护一个
directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]
数组可以实现转向
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
if not matrix or not matrix[0]:
return [] #异常输入检验
rows, columns = len(matrix), len(matrix[0])
visited = [[False] * columns for _ in range(rows)] #生成一个同样大小的Boolean 值数组来记录是否被访问过。
total = rows * columns#总共的元素个数
order = [0] * total#用来放最后的记录
directions = [[0, 1], [1, 0], [0, -1], [-1, 0]] #四个方向分别是列+1 向右,行+1 向下,列-1 向左,行-1 向上
row, column = 0, 0 #起始的位置 左上角00
directionIndex = 0 #用整数值记录当前方向 起始是向右
for i in range(total):
order[i] = matrix[row][column] #放入一个值
visited[row][column] = True#记录
nextRow, nextColumn = row + directions[directionIndex][0], column + directions[directionIndex][1]#下一个假定位置坐标
if not (0 <= nextRow < rows and 0 <= nextColumn < columns and not visited[nextRow][nextColumn]): #如果假定坐标没有在边界内或已被访问
directionIndex = (directionIndex + 1) % 4#转换方向
row += directions[directionIndex][0] #下一个行坐标
column += directions[directionIndex][1]#下一个列坐标
return order
时间复杂度 O(mn)空间复杂度O(mn)
每个元素都要访问一边,并要维护一个布尔数组
第二种解法和自己想的四个函数有相同之处,区别在于比我多了一个(bottom right)
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
if not matrix or not matrix[0]:
return []
rows=len(matrix)
cols=len(matrix[0])
left,right,top,bottom=0,cols-1,0,rows-1
ans=[]
while(left<=right and bottom>=top):
for c in range(left,right+1):
ans.append(matrix[top][c])
for r in range(top+1,bottom+1):
ans.append(matrix[r][right])
if(left<right and bottom > top):
for c in range (right-1,left,-1):
ans.append(matrix[bottom][c])
for r in range (bottom,top,-1):
ans.append(matrix[r][left])
left,right,top,bottom=left+1,right-1,top+1,bottom-1
return ans
评论区一个大佬的方法 能通过24/27个用例
还是值得一看的。
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
ans = []
while matrix:
ans.extend(matrix[0])#取一行
matrix = list(zip(* matrix[1:]))[::-1]#剩下的反转矩阵并倒序
return ans
############################################
两次二分
先找右侧边界,再找左侧边界。 时间复杂度O(logn)
class Solution:
def search(self, nums: [int], target: int) -> int:
# 搜索右边界 right
i, j = 0, len(nums) - 1
while i <= j:
m = (i + j) // 2
if nums[m] <= target: i = m + 1
else: j = m - 1
right = i #right值会停在target 右侧一位数,j会等于target(如果有)
print(right)
print(nums[right])
# 若数组中无 target ,则提前返回
if j >= 0 and nums[j] != target: return 0
# 搜索左边界 left
i = 0
while i <= j:
m = (i + j) // 2
if nums[m] < target: i = m + 1
else: j = m - 1
left = j
return right - left - 1
二分,返回右子数组的首位元素
class Solution:
def missingNumber(self, nums: List[int]) -> int:
i=0
j=len(nums)-1
while(i<=j):
m=(i+j)//2
if(nums[m]==m):
i=m+1
else:
j=m-1
return i
暴力
nums=[0,1,2,3,4,5,6,7,9]
now=sum(nums)
full=0
for x in range(0,len(nums)+1):
full=full+x
print(full-now)