目录
53. 最大子序和
# 53. 最大子数组和
# 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
# 子数组 是数组中的一个连续部分。
# 输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
# 输出:6
# 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
class Solution:
# def maxSubArray(self, nums: List[int]) -> int:
def maxSubArray(self, nums):
dp=nums
for i in range(1,len(nums)):
dp[i]=max(dp[i-1]+nums[i],nums[i])
return max(dp)
33. 搜索旋转排序数组
# 33. 搜索旋转排序数组
# 整数数组 nums 按升序排列,数组中的值 互不相同 。
# 在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为[4,5,6,7,0,1,2] 。
# 给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回-1。
# 你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。
#
# 输入:nums = [4,5,6,7,0,1,2], target = 0
# 输出:4
class Solution:
# def search(self, nums: List[int], target: int) -> int:
def search(self, nums, target) :
n=len(nums)
l,r=0,n-1
while(l<r):
m=(l+r)//2
if(nums[-1]>=nums[m]):
r=m
else:
l=m+1
if(target>nums[-1]):
l,r=0,l
else:
l, r = l, n-1
while(l<r):
m=(l+r)//2
if(nums[m]>=target):
r=m
else:
l=m+1
ans=-1
if(nums[l]==target):
ans=l
return ans
三数之和
# 15. 三数之和
# 给你一个包含 n 个整数的数组nums,判断nums中是否存在三个元素 a,b,c ,使得a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
# 注意:答案中不可以包含重复的三元组
# 输入:nums = [-1,0,1,2,-1,-4]
# 输出:[[-1,-1,2],[-1,0,1]]
class Solution:
# def threeSum(self, nums: List[int]) -> List[List[int]]:
def threeSum(self, nums):
nums.sort()
n=len(nums)
ans=[]
for i in range(n-2):
if i>0 and nums[i-1]==nums[i]:
continue
if nums[i]+nums[i+1]+nums[i+2]>0:
break
if nums[i]+nums[n-1]+nums[n-2]<0:
continue
l,r=i+1,n-1
while(l<r):
total=nums[i]+nums[l]+nums[r]
if(total==0):
ans.append([nums[i],nums[l],nums[r]])
while(l<r and nums[l+1]==nums[l]):
l+=1
l+=1
while(l<r and nums[r-1]==nums[r]):
r-=1
r-=1
elif(total<0):
l+=1
else:
r-=1
return ans
s=Solution()
# nums = [-1,0,1,2,-1,-4]
nums=[-2,0,0,2,2]
r=s.threeSum(nums)
print(r)
121. 买卖股票的最佳时机
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
class Solution:
def maxProfit(self, prices: List[int]) -> int:
dp=[0]*len(prices)
min_i=0
for i in range(1,len(prices)):
if(prices[min_i]>prices[i]):
min_i=i
if(min_i!=i):
dp[i]=prices[i]-prices[min_i]
return max(dp)
4. 寻找两个正序数组的中位数
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
#https://leetcode.cn/problems/median-of-two-sorted-arrays/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-2/
# 输入:nums1 = [1,3], nums2 = [2]
# 输出:2.00000
# 解释:合并数组 = [1,2,3] ,中位数 2
class Solution:
# def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
def findMedianSortedArrays(self, nums1, nums2):
m=len(nums1)
n=len(nums2)
if(m>n):
return self.findMedianSortedArrays(nums2,nums1)
print(m,n)
min_i,max_i=0,m
while(min_i<=max_i):
i=(min_i+max_i)//2
j=(m+n+1)//2-i
# print("i,j",i,j)
if(i>0 and j<n and nums1[i-1]>nums2[j]):
max_i-=1
elif(j>0 and i<m and nums2[j-1]>nums1[i]):
min_i+=1
else:
max_left=0
if(i==0):
max_left=nums2[j-1]
elif(j==0):
max_left=nums1[i-1]
else:
max_left=max(nums1[i-1],nums2[j-1])
if(m+n)%2==1:
return max_left
min_right=0
if(i==m):
min_right=nums2[j]
elif(j==n):
min_right=nums1[i]
else:
min_right=min(nums1[i],nums2[j])
if((m+n)%2)==0:
return (max_left+min_right)/2
return 0.0
s=Solution()
# nums1 = [1,3]
# nums2 = [2]
# nums1=[]
# nums2=[1]
nums1=[2]
nums2=[]
r=s.findMedianSortedArrays(nums1,nums2)
print(r)
695. 岛屿的最大面积
# 给你一个大小为 m x n 的二进制矩阵 grid 。
# 岛屿是由一些相邻的1(代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设grid 的四个边缘都被 0(代表水)包围着。
# 岛屿的面积是岛上值为 1 的单元格的数目。
#
# 计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0
# 输入:grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]]
# 输出:6
# 解释:答案不应该是 11 ,因为岛屿只能包含水平或垂直这四个方向上的 1 。
class Solution:
# def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
def maxAreaOfIsland(self, grid):
def dfs(i,j):
area=0
if i>=0 and i<len(grid) and j>=0 and j<len(grid[0]) and grid[i][j] and not flag[i][j]:
flag[i][j]=True
area=dfs(i-1,j)+dfs(i+1,j)+dfs(i,j-1)+dfs(i,j+1)+grid[i][j]
return area
ans=0
flag=[[False]*len(grid[0]) for i in range(len(grid))]
for i in range(len(grid)):
for j in range(len(grid[0])):
if(grid[i][j]==1):
area=dfs(i,j)
ans=max(area,ans)
return ans
s=Solution()
grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]]
r=s.maxAreaOfIsland(grid)
print(r)
54. 螺旋矩阵
# 54. 螺旋矩阵
# 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
# 输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
# 输出:[1,2,3,6,9,8,7,4,5]
class Solution:
# def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
def spiralOrder(self, matrix) :
m,n=len(matrix),len(matrix[0])
t,b,l,r=0,m-1,0,n-1
ans=[]
while(t<=b and l<=r):
for i in range(l,r+1): #上
ans.append(matrix[t][i])
t+=1
for i in range(t,b+1): #右
ans.append(matrix[i][r])
r-=1
if(l<=r and t<=b): #上、右均变化,防止重复计算
for i in range(r,l-1,-1): #下
ans.append(matrix[b][i])
b-=1
for i in range(b,t-1,-1): #左
ans.append(matrix[i][l])
l+=1
return ans
s=Solution()
matrix = [[1,2,3],[4,5,6],[7,8,9]]
r=s.spiralOrder(matrix)
print(r)
88. 合并两个有序数组
# 88. 合并两个有序数组
# 给你两个按 非递减顺序 排列的整数数组nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
#
# 请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
#
# 注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
#
# 输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
# 输出:[1,2,2,3,5,6]
# 解释:需要合并 [1,2,3] 和 [2,5,6] 。
# 合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
class Solution:
# def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
# """
# Do not return anything, modify nums1 in-place instead.
# """
def merge(self, nums1, m, nums2, n):
i,j,k=m-1,n-1,m+n-1
while i>=0 and j>=0:
if(nums1[i]>nums2[j]):
nums1[k]=nums1[i]
i-=1
else:
nums1[k]=nums2[j]
j-=1
k-=1
while i>=0:
nums1[k]=nums1[i]
k-=1
i-=1
while j>=0:
nums1[k]=nums2[j]
k-=1
j-=1
# nums1 = [1,2,3,0,0,0]
# m = 3
# nums2 = [2,5,6]
# n = 3
nums1=[0]
m=0
nums2=[1]
n=1
s=Solution()
s.merge(nums1,m,nums2,n)
print(nums1)
152. 乘积最大子数组
# 152. 乘积最大子数组
# 给你一个整数数组 nums,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
# 测试用例的答案是一个32-位 整数。
#
# 子数组 是数组的连续子序列。
# 输入: nums = [2,3,-2,4]
# 输出: 6
# 解释: 子数组 [2,3] 有最大乘积 6。
class Solution:
# def maxProduct(self, nums: List[int]) -> int:
def maxProduct(self, nums) :
dp_min=[0]*len(nums)
dp_max=[0]*len(nums)
dp_max[0]=dp_min[0]=nums[0]
for i in range(1,len(nums)):
dp_min[i]=min(dp_max[i-1]*nums[i],dp_min[i-1]*nums[i],nums[i])
dp_max[i] = max(dp_max[i - 1] * nums[i], dp_min[i - 1] * nums[i], nums[i])
return max(dp_max)
# class Solution:
# def maxProduct(self, nums: List[int]) -> int:
# if not nums:
# return 0
# max_pro,min_pro,min_cur,max_cur=nums[0],nums[0],nums[0],nums[0]
# for i in range(1,len(nums)):
# min_cur,max_cur=min(min(nums[i],min_cur*nums[i]),max_cur*nums[i]),max(min_cur*nums[i],max(max_cur*nums[i],nums[i]))
# if(max_pro<max_cur):
# max_pro=max_cur
# if(min_pro>min_cur):
# min_pro=min_cur
# print("min_pro:",min_pro)
# print("max_pro:",max_pro)
# return max_pro
s=Solution()
# nums=[2,3,-2,4]
nums=[-2,3,-4]
r=s.maxProduct(nums)
print(r)
42. 接雨水
# 42. 接雨水
# 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
# 输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
# 输出:6
# 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
class Solution:
# def trap(self, height: List[int]) -> int:
def trap(self, height):
left=[0]*len(height)
right=[0]*len(height)
left[0]=height[0]
right[-1]=height[-1]
for i in range(1,len(height)):
left[i]=max(left[i-1],height[i])
for i in range(len(height)-2,-1,-1):
right[i]=max(right[i+1],height[i])
ans=0
for i in range(len(height)):
ans+=min(left[i],right[i])-height[i]
return ans
64. 最小路径和
# 64. 最小路径和
# 给定一个包含非负整数的 mxn网格grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
# 说明:每次只能向下或者向右移动一步。
# 输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
# 输出:7
# 解释:因为路径 1→3→1→1→1 的总和最小。
class Solution:
# def minPathSum(self, grid: List[List[int]]) -> int:
def minPathSum(self, grid):
dp=[[0]*len(grid[0]) for i in range(len(grid))]
dp[0][0]=grid[0][0]
for i in range(1,len(grid)):
dp[i][0]=grid[i][0]+dp[i-1][0]
for i in range(1,len(grid[0])):
dp[0][i]=grid[0][i]+dp[0][i-1]
for i in range(1,len(grid)):
for j in range(1,len(grid[0])):
dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j]
return dp[-1][-1]
grid = [[1,3,1],[1,5,1],[4,2,1]]
s=Solution()
r=s.minPathSum(grid)
print(r)
1. 两数之和
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
h={}
for i,num in enumerate(nums) :
if target-num in h:
return [h[target-num],i]
h[num]=i
return [-1,-1]
123. 买卖股票的最佳时机 III
# 123. 买卖股票的最佳时机 III
# 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。
# 设计一个算法来计算你所能获取的最大利润。你最多可以完成两笔交易。
# 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
#
# 输入:prices = [3,3,5,0,0,3,1,4]
# 输出:6
# 解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。
# 随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。
class Solution:
# def maxProfit(self, prices: List[int]) -> int:
def maxProfit(self, prices):
left=[0]*len(prices)
left_min=prices[0]
right=[0]*len(prices)
for i in range(1,len(prices)):
left_min=min(prices[i],left_min)
left[i]=prices[i]-left_min
right_max=prices[-1]
for i in range(len(prices)-2,0,-1):
right[i]=right_max-prices[i+1]
right_max = max(prices[i], right_max)
right[i]=max(right[i],right[i+1])
ans=max(left)
# print(prices)
# print(left)
# print(right)
for i in range(len(prices)):
ans=max(left[i]+right[i],ans)
return ans
s=Solution()
prices = [3,3,5,0,0,3,1,4]
r=s.maxProfit(prices)
print(r)
48. 旋转图像
# 48. 旋转图像
# 给定一个 n×n 的二维矩阵matrix 表示一个图像。请你将图像顺时针旋转 90 度。
# 你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
# 输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
# 输出:[[7,4,1],[8,5,2],[9,6,3]]
# class Solution:
#
# def rotate(self, matrix: List[List[int]]) -> None:
# """
# Do not return anything, modify matrix in-place instead.
# """
#
# r_s = 0 # 行开始
# r_e = len(matrix) - 1 # 行结束
# c_s = 0 # 列开始
# c_e = len(matrix[0]) - 1 # 列结束
# n = len(matrix)
#
# while (r_s < r_e):
# for i in range(c_s, c_e):
# '''
# 从外至内,顺方向替换,各个位置的变换关系如下所示
# matrix[r_s][i]->matrix[i][c_e]
# matrix[i][c_e]->matrix[r_e][n-i-1]
# matrix[r_e][n-i-1]->matrix[n-i-1][c_s]
# matraix[n-i-1][c_s]->matraix[r_s][i]
# '''
#
# t = matrix[r_s][i]
# matrix[r_s][i] = matrix[n - i - 1][c_s]
# matrix[n - i - 1][c_s] = matrix[r_e][n - i - 1]
# matrix[r_e][n - i - 1] = matrix[i][c_e]
# matrix[i][c_e] = t
#
# r_s += 1
# r_e -= 1
# c_s += 1
# c_e -= 1
class Solution:
# def rotate(self, matrix: List[List[int]]) -> None:
def rotate(self, matrix):
"""
Do not return anything, modify matrix in-place instead.
"""
t,b,l,r,m,n=0,len(matrix)-1,0,len(matrix[0])-1,len(matrix)-1,len(matrix[0])-1
while(t<b):
for k in range(l,r):
# print(t,b,l,r)
# print('(',t,k,')','(',m-k,l,')','(',b,n-k,')','(',k,r,')')
# print(matrix[t][k],matrix[m-k][l],matrix[b][n-k],matrix[k][r])
tmp=matrix[t][k]
matrix[t][k]=matrix[m-k][l]
matrix[m-k][l]=matrix[b][n-k]
matrix[b][n-k]=matrix[k][r]
matrix[k][r]=tmp
# print( matrix[t][k],matrix[m-k][l],matrix[b][n-k],matrix[k][r])
t+=1
b-=1
l+=1
r-=1
matrix = [[1,2,3],[4,5,6],[7,8,9]]
s=Solution()
print(matrix)
r=s.rotate(matrix)
print(matrix)
34. 在排序数组中查找元素的第一个和最后一个位置
# 34. 在排序数组中查找元素的第一个和最后一个位置
# 给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
# 如果数组中不存在目标值 target,返回[-1, -1]。
# 你必须设计并实现时间复杂度为O(log n)的算法解决此问题。
# 输入:nums = [5,7,7,8,8,10], target = 8
# 输出:[3,4]
class Solution:
# def searchRange(self, nums: List[int], target: int) -> List[int]:
def searchRange(self, nums, target) :
if not nums:
return [-1,-1]
ans=[-1,-1]
l,r=0,len(nums)-1
while(l<r):
m=(l+r)//2
print("1:",l,r,m, nums[m])
if(nums[m]>=target):
r=m
else:
l=m+1
if(l<len(nums) and nums[l]!=target):
return ans
else:
ans[0]=l
l, r = 0, len(nums) - 1
while(l<r):
m=(l+r+1)//2
print("2:",l,r,m, nums[m])
if(nums[m]<=target):
l=m
else:
r=m-1
if (l<len(nums) and nums[l] != target):
return [-1,-1]
else:
ans[1] = l
return ans
s=Solution()
# nums = [5,7,7,8,8,10]
# target = 8
nums =[]
target =0
r=s.searchRange(nums,target)
print(r)
31. 下一个排列
# 31. 下一个排列
# 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。
#
# 例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。
# 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。
#
# 例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。
# 类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。
# 而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。
# 给你一个整数数组 nums ,找出 nums 的下一个排列。
#
# 必须 原地 修改,只允许使用额外常数空间。
# 输入:nums = [1,2,3]
# 输出:[1,3,2]
# https://leetcode.cn/problems/next-permutation/solution/fen-6bu-fen-xi-si-lu-qing-xi-ji-bai-9982-pwr5/ 这个解析较为详细
class Solution:
# def nextPermutation(self, nums: List[int]) -> None:
# """
# Do not return anything, modify nums in-place instead.
# """
def nextPermutation(self, nums) :
i=len(nums)-1
while(i>0 and nums[i-1]>=nums[i]): #找到反向第一对顺序下标
i-=1
if(i>0): #i-1为反向第一对顺下较小数的下标,当==0时,说明整个序列为降序,为最大排序,直接反转即可
j=len(nums)-1
while(j>i-1 and nums[j]<=nums[i-1]): #找到反向第一个大于nums[i]的下标
j-=1
nums[i-1],nums[j]=nums[j],nums[i-1]
print(i-1,j)
l,r=i,len(nums)-1
while(l<r): #i到len(nums)为反向降序排列,即最大的排序序列,反转将其变为最小的序列
nums[l],nums[r]=nums[r],nums[l]
l+=1
r-=1
s=Solution()
arr = [1,2,3]
r=s.nextPermutation(arr)
print(arr)
85. 最大矩形
class Solution:
# def maximalRectangle(self, matrix: List[List[str]]) -> int:
def maximalRectangle(self, matrix):
m,n=len(matrix),len(matrix[0])
pillar=[[0]*len(matrix[0]) for i in range(len(matrix))]
for i in range(m):
for j in range(n):
if matrix[i][j]=='1':
if i==0:
pillar[i][j]=1
else:
pillar[i][j]=pillar[i-1][j]+1
res=0
for i in range(m):
# 柱形的最大面积求法,84题
area_i=0
left,right=[0]*n,[0]*n
cur_min=[]
for j in range(n):
while cur_min and pillar[i][j]<=pillar[i][cur_min[-1]]:
cur_min.pop()
if cur_min:
left[j]=cur_min[-1]
else:
left[j]=-1
cur_min.append(j)
cur_min=[]
for j in range(n-1,-1,-1):
while cur_min and pillar[i][j]<=pillar[i][cur_min[-1]]:
cur_min.pop()
if cur_min:
right[j]=cur_min[-1]
else:
right[j]=n
cur_min.append(j)
for j in range(n):
area_i=max(area_i,(right[j]-left[j]-1)*pillar[i][j])
res=max(res,area_i)
return res
560. 和为K的子数组
给你一个整数数组 nums
和一个整数 k
,请你统计并返回 该数组中和为 k
的连续子数组的个数 。
输入:nums = [1,1,1], k = 2 输出:2
class Solution:
# def subarraySum(self, nums: List[int], k: int) -> int:
def subarraySum(self, nums, k) :
from collections import defaultdict
res=0
n=len(nums)
h=defaultdict(int)
pre_sum=0
h[0]=1
for i in range(n):
pre_sum+=nums[i]
if (pre_sum-k) in h:
res+=h[pre_sum-k]
h[pre_sum]=h[pre_sum]+1
return res
56. 合并区间
# 56. 合并区间
# 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间
# 输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
# 输出:[[1,6],[8,10],[15,18]]
# 解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
class Solution:
# def merge(self, intervals: List[List[int]]) -> List[List[int]]:
def merge(self, intervals) :
intervals.sort(key=lambda x:x[0])
res=[intervals[0]]
for i in range(1,len(intervals)):
if res[-1][1]>=intervals[i][0]:
res[-1][1]=max(res[-1][1],intervals[i][1])
else:
res.append(intervals[i])
return res
intervals = [[1,3],[2,6],[8,10],[15,18]]
s=Solution()
r=s.merge(intervals)
print(r)
45. 跳跃游戏 II
# 45. 跳跃游戏 II
# 给你一个非负整数数组nums ,你最初位于数组的第一个位置。
# 数组中的每个元素代表你在该位置可以跳跃的最大长度。
# 你的目标是使用最少的跳跃次数到达数组的最后一个位置。
# 假设你总是可以到达数组的最后一个位置。
#
# 输入: nums = [2,3,1,1,4]
# 输出: 2
# 解释: 跳到最后一个位置的最小跳跃数是 2。
# 从下标为 0 跳到下标为 1 的位置,跳1步,然后跳3步到达数组的最后一个位置。
# 在具体的实现中,我们维护当前能够到达的最大下标位置,记为边界。我们从左到右遍历数组,到达边界时,更新边界并将跳跃次数增加 1。
# 在遍历数组时,我们不访问最后一个元素,这是因为在访问最后一个元素之前,我们的边界一定大于等于最后一个位置,否则就无法跳到最后一个位置了。如果访问最后一个元素,在边界正好为最后一个位置的情况下,我们会增加一次「不必要的跳跃次数」,因此我们不必访问最后一个元素。
# 正向最大可达,上一次跳跃结束时,进行计数,避免无效的计数
class Solution:
# def jump(self, nums: List[int]) -> int:
def jump(self, nums) :
cnt=0
max_jump=0
last_jump=0
for i in range(len(nums)-1):
if(i<=max_jump):
max_jump=max(max_jump,nums[i]+i)
if (i==last_jump): # 1-nums[i]遍历完了,并且找到这个区间内最优的跳跃方式
cnt+=1
last_jump=max_jump
return cnt
# nums = [2,3,1,1,4]
nums =[7,0,9,6,9,6,1,7,9,0,1,2,9,0,3]
s=Solution()
r=s.jump(nums)
print(r)
84. 柱状图中最大的矩形
# 84. 柱状图中最大的矩形
# 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
# 求在该柱状图中,能够勾勒出来的矩形的最大面积。
# 输入:heights = [2,1,5,6,2,3]
# 输出:10
# 解释:最大的矩形为图中红色区域,面积为 10
class Solution:
# def largestRectangleArea(self, heights: List[int]) -> int:
def largestRectangleArea(self, heights) :
left=[0]*len(heights)
right=[0]*len(heights)
st=[]
for i in range(len(heights)):
while st and heights[i]<=heights[st[-1]]: #left[i]记录第一个比height[i]大的下标
st.pop()
if st:
left[i]=(st[-1])
else:
left[i]=-1
st.append(i)
st=[]
for i in range(len(heights)-1,-1,-1):
while st and heights[i]<=heights[st[-1]]: #right[i]记录第一个比height[i]大的下标
st.pop()
if st:
right[i]=st[-1]
else:
right[i]=len(heights)
st.append(i)
# print(heights)
# print(left)
# print(right)
area=0
for i in range(len(heights)):
area=max(area,(right[i]-left[i]-1)*heights[i]) #left[i]满足height[i]最小的前一个下标, right[i]满足height[i]最小的后一个下标
return area
s=Solution()
heights = [2,1,5,6,2,3]
r=s.largestRectangleArea(heights)
print(r)
128. 最长连续序列
# 128. 最长连续序列
# 给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
# 请你设计并实现时间复杂度为O(n) 的算法解决此问题。
# 输入:nums = [100,4,200,1,3,2]
# 输出:4
# 解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
class Solution:
# def longestConsecutive(self, nums: List[int]) -> int:
def longestConsecutive(self, nums) :
num_dict={}
for num in nums:
num_dict[num]=1
ans=0
for num in nums:
num=num
if num-1 not in num_dict: #不重复计算已经判断过的连续子串
k=1
num+=1
while(num in num_dict):
k+=1
num+=1
ans=max(ans,k)
k=0
return ans
122. 买卖股票的最佳时机 II
# 122. 买卖股票的最佳时机 II
# 给你一个整数数组 prices ,其中prices[i] 表示某支股票第 i 天的价格。
#
# 在每一天,你可以决定是否购买和/或出售股票。你在任何时候最多只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
#
# 返回 你能获得的 最大 利润。
# 输入:prices = [7,1,5,3,6,4]
# 输出:7
# 解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
# 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。
# 总利润为 4 + 3 = 7 。
class Solution:
# def maxProfit(self, prices: List[int]) -> int:
def maxProfit(self, prices) :
ans=0
for i in range(1,len(prices)):
ans+=max(0,prices[i]-prices[i-1])
return ans
s=Solution()
prices = [7,1,5,3,6,4]
r=s.maxProfit(prices)
print(r)
62. 不同路径
# 62. 不同路径
# 一个机器人位于一个 m x n网格的左上角 (起始点在下图中标记为 “Start” )。
# 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
# 问总共有多少条不同的路径?
# 输入:m = 3, n = 7
# 输出:28
class Solution:
# def uniquePaths(self, m: int, n: int) -> int:
def uniquePaths(self, m, n) :
dp=[[0]*n for i in range(m)]
for i in range(m):
dp[i][0]=1
for j in range(n):
dp[0][j]=1
for i in range(1,m):
for j in range(1,n):
dp[i][j]=dp[i-1][j]+dp[i][j-1]
return dp[-1][-1]
m,n=3,7
s=Solution()
r=s.uniquePaths(m,n)
print(r)
11. 盛最多水的容器
# 11. 盛最多水的容器
# 给定一个长度为 n 的整数数组height。有n条垂线,第 i 条线的两个端点是(i, 0)和(i, height[i])。
# 找出其中的两条线,使得它们与x轴共同构成的容器可以容纳最多的水。
#
# 返回容器可以储存的最大水量。
#
# 说明:你不能倾斜容器。
# 输入:[1,8,6,2,5,4,8,3,7]
# 输出:49
# 解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为49。
class Solution:
# def maxArea(self, height: List[int]) -> int:
def maxArea(self, height) :
l,r=0,len(height)-1
area=0
while(l<r):
t=min(height[l],height[r])*(r-l)
area=max(area,t)
if height[l]<height[r]:
l+=1
else:
r-=1
return area
s=Solution()
# heights=[1,8,6,2,5,4,8,3,7]
# heights=[1,1]
heights=[1,2,1]
r=s.maxArea(heights)
print(r)
41. 缺失的第一个正数
# 41. 缺失的第一个正数
# 给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
# 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。
# 输入:nums = [1,2,0]
# 输出:3
class Solution:
# def firstMissingPositive(self, nums: List[int]) -> int:
def firstMissingPositive(self, nums):
for i in range(len(nums)):
while nums[i]>0 and nums[i]<=len(nums) and nums[nums[i]-1]!=nums[i]:
t=nums[nums[i]-1]
nums[nums[i]-1]=nums[i]
nums[i]=t
# print(nums)
k=0
while k<len(nums):
if k+1!=nums[k]:
return k+1
k+=1
return k+1
39. 组合总和
# 39. 组合总和
# 给你一个 无重复元素 的整数数组candidates 和一个目标整数target,找出candidates中可以使数字和为目标数target 的 所有不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
#
# candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
#
# 对于给定的输入,保证和为target 的不同组合数少于 150 个。
# 输入:candidates = [2,3,6,7], target = 7
# 输出:[[2,2,3],[7]]
# 解释:
# 2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
# 7 也是一个候选, 7 = 7 。
# 仅有这两种组合。
class Solution:
# def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
def combinationSum(self, candidates, target):
ans=[]
def dfs(s,target,t):
if target==0:
ans.append(t)
if target<0:
return
for i in range(s,len(candidates)):
if i>0 and candidates[i-1]==candidates[i]:
continue
dfs(i,target-candidates[i],t+[candidates[i]])
dfs(0,target,[])
return ans
s=Solution()
candidates = [2,3,6,7]
target = 7
r=s.combinationSum(candidates,target)
print(r)
611. 有效三角形的个数
# 611. 有效三角形的个数
# 给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。
# 输入: nums = [2,2,3,4]
# 输出: 3
# 解释:有效的组合是:
# 2,3,4 (使用第一个 2)
# 2,3,4 (使用第二个 2)
# 2,2,3
class Solution:
# def triangleNumber(self, nums: List[int]) -> int:
def triangleNumber(self, nums) :
nums.sort()
n=len(nums)
ans=0
for i in range(n):
l,r=0,i-1
while l<r:
if nums[l]+nums[r]>nums[i]: #固定最大的,只用判断一组两边之和大于第三 nums边;较小的元素逐一靠近
# print(l,r)
ans+=max((r-l),0)
r-=1
else:
l+=1
return ans
nums = [2,2,3,4]
s=Solution()
r=s.triangleNumber(nums)
print(r)
55. 跳跃游戏
# 55. 跳跃游戏
# 给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。
# 数组中的每个元素代表你在该位置可以跳跃的最大长度。
# 判断你是否能够到达最后一个下标。
# 输入:nums = [2,3,1,1,4]
# 输出:true
# 解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。
# nums = [3,2,1,0,4]
# 输出:false
# 我们依次遍历数组中的每一个位置,并实时维护 最远可以到达的位置。对于当前遍历到的位置
# x,如果它在 最远可以到达的位置 的范围内,那么我们就可以从起点通过若干次跳跃到达该位置,因此我们可以用
# x+nums[x] 更新 最远可以到达的位置。
# 在遍历的过程中,如果 最远可以到达的位置 大于等于数组中的最后一个位置,那就说明最后一个位置可达,我们就可以直接返回 True 作为答案。反之,如果在遍历结束后,最后一个位置仍然不可达,我们就返回 False 作为答案。
class Solution:
# def canJump(self, nums: List[int]) -> bool:
def canJump(self, nums):
max_jump=0
for i in range(len(nums)):
if(i<=max_jump):
max_jump=max(max_jump,nums[i]+i)
if(max_jump>=len(nums)-1):
return True
return False
# nums = [2,3,1,1,4]
# nums = [3,2,1,0,4]
nums=[1,2,3]
s=Solution()
r=s.canJump(nums)
print(r)
105. 从前序与中序遍历序列构造二叉树
# 105. 从前序与中序遍历序列构造二叉树
# 给定两个整数数组preorder 和 inorder,其中preorder 是二叉树的先序遍历, inorder是同一棵树的中序遍历,请构造二叉树并返回其根节点。
#
# 输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
# 输出: [3,9,20,null,null,15,7]
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
# def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
def buildTree(self, preorder, inorder):
if not preorder and not inorder:
return None
val=preorder[0]
val_i=inorder.index(val)
root=TreeNode(val)
root.left=self.buildTree(preorder[1:val_i+1],inorder[0:val_i])
root.right=self.buildTree(preorder[val_i+1:],inorder[val_i+1:])
return root
169. 多数元素
# 169. 多数元素
# 给定一个大小为 n 的数组nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于⌊ n/2 ⌋的元素。
# 你可以假设数组是非空的,并且给定的数组总是存在多数元素。
# 输入:nums = [3,2,3]
# 输出:3
class Solution:
# def majorityElement(self, nums: List[int]) -> int:
def majorityElement(self, nums):
num=nums[0]
cnt=1
k=1
while k<len(nums):
if(nums[k]==num):
cnt+=1
else:
cnt-=1
if(cnt<0):
num=nums[k]
cnt=1
k+=1
return num
nums = [3,2,3,2,2,1,1,2,2]
s=Solution()
r=s.majorityElement(nums)
print(r)
209. 长度最小的子数组
# 209. 长度最小的子数组
# 给定一个含有n个正整数的数组和一个正整数 target 。
#
# 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组[numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
# 输入:target = 7, nums = [2,3,1,2,4,3]
# 输出:2
# 解释:子数组 [4,3] 是该条件下的长度最小的子数组。
class Solution:
# def minSubArrayLen(self, target: int, nums: List[int]) -> int:
def minSubArrayLen(self, target, nums) :
l,r=0,0
total=0
ans=len(nums)
flag=True
while r<len(nums):
total+=nums[r]
r+=1
while total>=target:
flag=False
ans=min(ans,r-l)
total -= nums[l]
l+=1
if(flag):
return 0
return ans
162. 寻找峰值
# 162. 寻找峰值
# 峰值元素是指其值严格大于左右相邻值的元素。
# 给你一个整数数组nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
# 你可以假设nums[-1] = nums[n] = -∞ 。
# 你必须实现时间复杂度为 O(log n) 的算法来解决此问题。
# 输入:nums = [1,2,3,1]
# 输出:2
# 解释:3 是峰值元素,你的函数应该返回其索引 2。
# 输入:nums = [1,2,1,3,5,6,4]
# 输出:1 或 5
# 解释:你的函数可以返回索引 1,其峰值元素为 2;或者返回索引 5, 其峰值元素为 6。
class Solution:
def findPeakElement(self, nums: List[int]) -> int:
l,r=0,len(nums)-1
while(l<r):
m=(l+r)//2
if(m>0 and nums[m]<=nums[m-1]) or (m<len(nums)-1 and nums[m]>nums[m+1]):
r=m
else:
l=m+1
return l
74. 搜索二维矩阵
与240算法解法一样
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
r,c=0,len(matrix[0])-1
while r<len(matrix) and c>=0:
if(matrix[r][c]==target):
return True
elif(matrix[r][c]>target):
c-=1
else:
r+=1
return False
40. 组合总和 II
# 40. 组合总和 II
# 给定一个候选人编号的集合candidates和一个目标数target,找出candidates中所有可以使数字和为target的组合。
# candidates中的每个数字在每个组合中只能使用一次。
# 注意:解集不能包含重复的组合。
# 输入: candidates = [10,1,2,7,6,1,5], target = 8,
# 输出:
# [
# [1,1,6],
# [1,2,5],
# [1,7],
# [2,6]
# ]
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
candidates.sort()
ans=[]
t=[]
def dfs(s,target):
if target==0:
ans.append(t[::])
return
if target<0:
return
for i in range(s,len(candidates)):
if(i>s and candidates[i-1]==candidates[i]):
continue
t.append(candidates[i])
dfs(i+1,target-candidates[i])
t.pop()
dfs(0,target)
return ans
1031. 两个非重叠子数组的最大和
# 1031. 两个非重叠子数组的最大和
# 给出非负整数数组 A ,返回两个非重叠(连续)子数组中元素的最大和,子数组的长度分别为 L 和 M。(这里需要澄清的是,长为L的子数组可以出现在长为M的子数组之前或之后。)
#
# 从形式上看,返回最大的 V,而 V = (A[i] + A[i+1] + ... + A[i+L-1]) + (A[j] + A[j+1] + ... + A[j+M-1]) 并满足下列条件之一:
#
# 0 <= i < i + L - 1 < j < j + M - 1 < A.length, 或
# 0 <= j < j + M - 1 < i < i + L - 1 < A.length
# 输入:A = [0,6,5,2,2,5,1,9,4], L = 1, M = 2
# 输出:20
# 解释:子数组的一种选择中,[9] 长度为 1,[6,5] 长度为 2。
# 思路:
# 考虑题意: 必然存在一条分界线把 A 拆分成两半,存在两大类情况:
# 长度为 L 的连续子数组在左边, 长度为 M 的连续子数组在右边
# 或者反过来长度为 M 的连续子数组在左边, 长度为 L 的连续子数组在右边
# 引入
#
# dp[i][0]: 从 A[0]-A[i] 连续 L 长度子数组最大的元素和
# dp[i][1]: 从 A[0]-A[i] 连续 M 长度子数组最大的元素和
# dp[i][2]: 从 A[i]-A[A.size()-1] 连续 L 长度子数组最大的元素和
# dp[i][3]: 从 A[i]-A[A.size()-1] 连续 M 长度子数组最大的元素和
# 某些超出范围的下标, 值设置为 0 (默认值)
# 代码中首先用滑动窗口计算了 dp, 然后将 dp 分成两组, 计算两大类情况下的结果,取最大值返回即可
#
class Solution:
# def maxSumTwoNoOverlap(self, nums: List[int], firstLen: int, secondLen: int) -> int:
def maxSumTwoNoOverlap(self, nums, firstLen, secondLen):
# 滑动窗口的值枚举
nums_win1=[] #firstLen为窗口的枚举
nums_win2=[] #secondLen为窗口的枚举
for i in range(len(nums)-firstLen+1):
nums_win1.append(sum(nums[i:i+firstLen]))
for i in range(len(nums)-secondLen+1):
nums_win2.append(sum(nums[i:i+secondLen]))
# print(nums,'\n',firstLen,secondLen,'\n',nums_win1,'\n',nums_win2)
ans=0
len1=len(nums)-firstLen+1
len2=len(nums)-secondLen+1
# print(len1,len2,min(len2-firstLen,len1),min(len1-secondLen,len2))
for i in range(1,len1): #i<len1;i+firstLen-1<len2
if(i+firstLen<len2+1):
ans=max(ans,max(nums_win1[0:i])+max(nums_win2[i-1+firstLen:]))
for i in range(1,len2): #i<len1;i+secondLen-1<len1
if(i+secondLen<len1+1):
ans=max(ans,max(nums_win2[0:i])+max(nums_win1[i+secondLen-1:]))
return ans
A = [0,6,5,2,2,5,1,9,4]
L = 1
M = 2
# A=[3,8,1,3,2,1,8,9,0] #29 [3,8,1] [8,9]
# L=3
# M=2
# A=[2,1,5,6,0,9,5,0,3,8] #31 [5,6,0,9] [0,3,8]
# M=4
# L=3
# A=[1,0,3]
# M=1
# L=2
s=Solution()
r=s.maxSumTwoNoOverlap(A,L,M)
print(r)
73. 矩阵置零
# 73. 矩阵置零
# 给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。
# 输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
# 输出:[[1,0,1],[0,0,0],[1,0,1]]
# 输入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
# 输出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]
class Solution:
# def setZeroes(self, matrix: List[List[int]]) -> None:
def setZeroes(self, matrix) :
"""
Do not return anything, modify matrix in-place instead.
"""
m,n=len(matrix),len(matrix[0])
col_zero=False
row_zero=False
for i in range(m):
if matrix[i][0]==0:
col_zero=True
for j in range(n):
if matrix[0][j]==0:
row_zero=True
for i in range(1,m):
for j in range(1,n):
if(matrix[i][j]==0):
matrix[i][0]=0
matrix[0][j]=0
for i in range(1,m):
if matrix[i][0]==0:
for j in range(n):
matrix[i][j]=0
for j in range(1,n):
if(matrix[0][j]==0):
for i in range(m):
matrix[i][j]=0
if col_zero:
for i in range(m):
matrix[i][0]=0
if row_zero:
for j in range(n):
matrix[0][j]=0
# matrix = [[1,1,1],[1,0,1],[1,1,1]]
matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
print(matrix)
s=Solution()
s.setZeroes(matrix)
print(matrix)
剑指 Offer 29. 顺时针打印矩阵
#输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
# 输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
# 输出:[1,2,3,6,9,8,7,4,5]
# 与54题的差异是这个matrix可以为空
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
if not matrix:
return []
m,n=len(matrix),len(matrix[0])
t,b,l,r=0,m-1,0,n-1
ans=[]
while(t<=b and l<=r):
for i in range(l,r+1): #上
ans.append(matrix[t][i])
t+=1
for i in range(t,b+1): #右
ans.append(matrix[i][r])
r-=1
if(l<=r and t<=b): #上、右均变化,防止重复计算
for i in range(r,l-1,-1): #下
ans.append(matrix[b][i])
b-=1
for i in range(b,t-1,-1): #左
ans.append(matrix[i][l])
l+=1
return ans
78. 子集
# 78. 子集
# 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
# 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
# 输入:nums = [1,2,3]
# 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
from typing import List
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
nums.sort()
res=[]
t=[]
def dfs(h):
res.append(t[::])
for i in range(h,len(nums)):
if(i>0 and nums[i-1]==nums[i]):
continue
t.append(nums[i])
dfs(i+1)
t.pop()
dfs(0)
return res
nums = [1,2,3]
s=Solution()
r=s.subsets(nums)
print(r)
面试题 10.03. 搜索旋转数组
# 面试题 10.03. 搜索旋转数组
# 搜索旋转数组。给定一个排序后的数组,包含n个整数,但这个数组已被旋转过很多次了,次数不详。请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的。若有多个相同元素,返回索引值最小的一个。
# 输入: arr = [15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14], target = 5
# 输出: 8(元素5在该数组中的索引)
# 输入:arr = [15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14], target = 11
# 输出:-1 (没有找到)
# https://leetcode.cn/problems/search-rotate-array-lcci/solution/er-fen-fa-by-armeria-program/ 图解很详细
from typing import List
class Solution:
def search(self, arr: List[int], target: int) -> int:
l,r=0,len(arr)-1
while(l<r):
m=(l+r)//2
print("#1:",l,r,m,arr[m])
if(arr[l]<arr[m]):
if(arr[l]<=target and target<=arr[m]): #左边界单调增且target在此区间
print('@1')
r=m
else:
print('@2')
l=m+1
elif(arr[l]>arr[m]):
if(arr[l]<=target or target<=arr[m]): #左边界不单调且target在此区间
print('@3')
r=m
else:
print('@4')
l=m+1
elif(arr[l]==arr[m]):
if(arr[l]==target):
print('@5')
r=l
else:
print('@6')
l+=1 #去掉重复的数
print("#2:",l,r)
return l if arr[l]==target else -1
# class Solution:
# def search(self, nums: List[int], target: int) -> int:
# if not nums:
# return -1
# left, right = 0, len(nums) - 1
# while left < right: # 循环结束条件left==right
# mid = (left + right) >> 1
# if nums[left] < nums[mid]: # 如果左值小于中值,说明左边区间升序
# if nums[left] <= target and target <= nums[mid]: # 如果目标在左边的升序区间中,右边界移动到mid
# print('@1')
# right = mid
# else: # 否则目标在右半边,左边界移动到mid+1
# print('@2')
# left = mid + 1
# elif nums[left] > nums[mid]: # 如果左值大于中值,说明左边不是升序,右半边升序
# if nums[left] <= target or target <= nums[mid]: # 如果目标在左边,右边界移动到mid
# print('@3')
# right = mid
# else: # 否则目标在右半边的升序区间中,左边界移动到mid+1
# print('@4')
# left = mid + 1
# elif nums[left] == nums[mid]: # 如果左值等于中值,可能是已经找到了目标,也可能是遇到了重复值
# if nums[left] != target: # 如果左值不等于目标,说明还没找到,需要逐一清理重复值
# print('@5')
# left += 1
# else: # 如果左值等于目标,说明已经找到最左边的目标值
# print('@6')
# right = left # 将右边界移动到left,循环结束
# return left if nums[left] == target else -1 # 返回left,或者-1
# a=[15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14]
# target=5
# a=[1,1,1,1,1,2,1,1,1]
# target=2
a=[5,5,5,1,2,3,4,5]
target=5
s=Solution()
r=s.search(a,target)
print(r)
153. 寻找旋转排序数组中的最小值
# 153. 寻找旋转排序数组中的最小值
# 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
# 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
# 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
# 注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。
# 给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
# 你必须设计一个时间复杂度为O(log n) 的算法解决此问题。
# 输入:nums = [3,4,5,1,2]
# 输出:1
# 解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。
from typing import List
class Solution:
def findMin(self, nums: List[int]) -> int:
l,r=0,len(nums)-1
while(l<r):
m=(l+r)//2
if(nums[m]<=nums[-1]):
r=m
else:
l=m+1
return nums[l]
509. 斐波那契数
# 509. 斐波那契数
# 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:\
# F(0) = 0,F(1) = 1
# F(n) = F(n - 1) + F(n - 2),其中 n > 1
# 给定 n ,请计算 F(n) 。
class Solution:
# def fib(self, n: int) -> int:
def fib(self, n) :
a,b=0,1
for i in range(n):
t=b
b=a+b
a=t
return a
s=Solution()
r=s.fib(2)
print(r)
287. 寻找重复数
# 287. 寻找重复数
# 给定一个包含n + 1 个整数的数组nums ,其数字都在[1, n]范围内(包括 1 和 n),可知至少存在一个重复的整数。
# 假设 nums 只有 一个重复的整数 ,返回这个重复的数 。
# 你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。
# 输入:nums = [1,3,4,2,2]
# 输出:2
class Solution:
# def findDuplicate(self, nums: List[int]) -> int:
def findDuplicate(self, nums) :
print("#",nums)
for i in range(len(nums)):
k=1
while nums[nums[i]-1]!=nums[i]: #交换多次次,将i-1的位置放值为i的nums[i]
t=nums[nums[i]-1]
nums[nums[i]-1]=nums[i]
nums[i]=t
k+=1
if (nums[nums[i] - 1] == nums[i] and nums[i] - 1 != i):
return nums[i]
return -1
s=Solution()
nums = [1,3,4,2,2]
r=s.findDuplicate(nums)
print(r)
#快慢指针的方法
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int slow = 0, fast = 0;
do {
slow = nums[slow];
fast = nums[nums[fast]];
} while (slow != fast);
slow = 0;
while (slow != fast) {
slow = nums[slow];
fast = nums[fast];
}
return slow;
}
};
718. 最长重复子数组
# 动态规划解法;a[i][j]表示nums1与nums2的公共最大公共字串的量
# class Solution:
# # def findLength(self, nums1: List[int], nums2: List[int]) -> int:
# def findLength(self, nums1, nums2):
# m,n=len(nums1),len(nums2)
# a=[[0]*(n+1) for i in range(m+1)]
#
# for i in range(m):
# for j in range(n):
# if(nums1[i]==nums2[j]):
# a[i+1][j+1]=a[i][j]+1
# else:
# a[i + 1][j + 1] = 0
# res=0
# for i in range(1,m+1):
# for j in range(1,n+1):
# res=max(res,a[i][j])
# return res
# 滑动窗口
# 我们可以枚举 A 和 B 所有的对齐方式。对齐的方式有两类:第一类为 A 不变,B 的首元素与 A 中的某个元素对齐;第二类为 B 不变,
# A 的首元素与 B 中的某个元素对齐。对于每一种对齐方式,我们计算它们相对位置相同的重复子数组即可。
class Solution:
# def findLength(self, nums1: List[int], nums2: List[int]) -> int:
def findLength(self, nums1, nums2):
m,n=len(nums1),len(nums2)
res=0
def maxLen(i,j,len): #i为a的开始;j为b的开始;len为保证两者不溢出的长度
max_len=0
cur_len=0
for k in range(len):
if(nums1[i+k]==nums2[j+k]):
cur_len+=1
else:
cur_len=0
max_len = max(max_len, cur_len)
# print(max_len)
return max_len
# nums1动对齐
for i in range(m):
l=min(n,m-i)
res = max(res, maxLen(i,0,l))
# nums2动对齐
for i in range(n):
l=min(m,n-i)
res=max(res,maxLen(0,i,l))
return res
189. 轮转数组
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n=len(nums)
k=k%n
# ans=nums[n-k:]+nums[0:n-k]
# print(ans) 这种方式正确,但是函数无返回
nums[n-k:]=nums[n-k:][::-1]
nums[0:n-k]=nums[0:n-k][::-1]
nums[:]=nums[::-1]
167. 两数之和 II - 输入有序数组
# 167. 两数之和 II - 输入有序数组
# 给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。
#
# 以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。
#
# 你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
#
# 你所设计的解决方案必须只使用常量级的额外空间。
# 输入:numbers = [2,7,11,15], target = 9
# 输出:[1,2]
# 解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
l,r=0,len(numbers)-1
while(l<r):
t=numbers[l]+numbers[r]
if(t==target):
return [l+1,r+1]
elif(t>target):
r-=1
else:
l+=1
return [-1,-1]
238. 除自身以外数组的乘积
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
ans=[1]*len(nums)
forward=[1]*len(nums)
for i in range(len(nums)-1):
forward[i+1]=forward[i]*nums[i]
# print(forward)
back=1
for i in range(len(nums)-1,-1,-1):
ans[i]=back*forward[i]
back*=nums[i]
return ans
79. 单词搜索
# 79. 单词搜索
#
# 给定一个m x n 二维字符网格board 和一个字符串单词word 。如果word 存在于网格中,返回 true ;否则,返回 false 。
#
# 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
#
# 输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
# 输出:true
class Solution:
# def exist(self, board: List[List[str]], word: str) -> bool:
def exist(self, board, word) :
def dfs(h,i,j):
if(h==len(word)):
return True
valid=False
if i>=0 and i<len(board) and j >=0 and j <len(board[0]) and not flag[i][j] and word[h]==board[i][j]:
flag[i][j] = True
valid=dfs(h+1,i+1,j) or dfs(h+1,i-1,j) or dfs(h+1,i,j-1) or dfs(h+1,i,j+1)
flag[i][j]=False
return valid
find=False
for i in range(len(board)):
for j in range(len(board[0])):
flag = [[False] * len(board[0]) for i in range(len(board))]
find=dfs(0,i,j)
if(find):
return True
return find
# board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]]
# word = "ABCCED"
# board = [["a","b"],["c","d"]]
# word = "acdb"
board =[["A","B","C","E"],["S","F","E","S"],["A","D","E","E"]]
word ="ABCESEEEFS"
s=Solution()
r=s.exist(board,word)
print(r)
剑指 Offer 04. 二维数组中的查找
# 剑指 Offer 04. 二维数组中的查找
# 在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
# [
# [1, 4, 7, 11, 15],
# [2, 5, 8, 12, 19],
# [3, 6, 9, 16, 22],
# [10, 13, 14, 17, 24],
# [18, 21, 23, 26, 30]
# ]
# 给定 target = 5,返回 true。
# 给定 target = 20,返回 false。
class Solution:
# def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool
def findNumberIn2DArray(self, matrix, target) :
if not matrix:
return False
i,j=0,len(matrix[0])-1
while i<len(matrix) and j>=0:
if target==matrix[i][j]:
return True
elif target>matrix[i][j]:
i+=1
else:
j-=1
return False
s=Solution()
matrix=[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
target=9
r=s.findNumberIn2DArray(matrix,target)
print(r)
670. 最大交换
# 670. 最大交换
# 给定一个非负整数,你至多可以交换一次数字中的任意两位。返回你能得到的最大值。
# 输入: 2736
# 输出: 7236
# 解释: 交换数字2和数字7
class Solution:
# def maximumSwap(self, num: int) -> int:
def maximumSwap(self, num):
s=str(num)
l,r=0,len(s)-1
h=[-1]*10
for i,c in enumerate(s):
num=int(c)-1
h[num]=i
print(h)
for j,c in enumerate(s):
t = int(c) - 1
for i in range(8, -1, -1):
if h[i] == -1:
continue
if(i>t and h[i]>j):
lis=list(s)
lis[h[i]],lis[j]=lis[j],lis[h[i]]
s=''.join(lis)
return int(s)
return int(s)
s=Solution()
# num=2736
num=9973
r=s.maximumSwap(num)
print(r)
75. 颜色分类
# 75. 颜色分类
# 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
#
# 我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
#
# 必须在不使用库的sort函数的情况下解决这个问题
# 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
#
# 我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
#
# 必须在不使用库的sort函数的情况下解决这个问题
# 输入:nums = [2,0,2,1,1,0]
# 输出:[0,0,1,1,2,2]
from typing import List
class Solution:
def sortColors(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
h=[0]*3
for num in nums:
h[num]+=1
k=0
for i in range(3):
for j in range(h[i]):
nums[k]=i
k+=1
nums = [2,0,2,1,1,0]
s=Solution()
s.sortColors(nums)
print(nums)
581. 最短无序连续子数组
给你一个整数数组 nums ,你需要找出一个 连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。
请你找出符合题意的 最短 子数组,并输出它的长度。
输入:nums = [2,6,4,8,10,9,15]
输出:5
解释:你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。
class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
left=[nums[0]]*len(nums)
right=[nums[-1]]*len(nums)
for i in range(1,len(nums)):
left[i]=max(left[i-1],nums[i])
for i in range(len(nums)-2,-1,-1):
right[i]=min(right[i+1],nums[i])
l,r=-1,-1
for i in range(len(nums)):
if left[i]>nums[i] or nums[i]>right[i]:
l=i
break
for i in range(len(nums)-1,-1,-1):
if left[i]>nums[i] or nums[i]>right[i]:
r=i
break
if l==r and l==-1:
return 0
return r-l+1
剑指 Offer 53 - I. 在排序数组中查找数字 I
# 剑指 Offer 53 - I. 在排序数组中查找数字 I
# 统计一个数字在排序数组中出现的次数。
# 输入: nums = [5,7,7,8,8,10], target = 8
# 输出: 2
class Solution:
def search(self, nums: List[int], target: int) -> int:
if len(nums) == 0:
return 0
l, r = 0, len(nums) - 1
while (l < r):
m = (l + r) // 2
if (nums[m] >= target):
r = m
else:
l = m + 1
if (nums[l] != target):
return 0
ans, l1 = 0, l
l, r = l, len(nums) - 1
while (l < r):
m = (l + r + 1) // 2
if (nums[m] <= target):
l = m
else:
r = m - 1
if (nums[l] == target):
ans = l - l1 + 1
return ans
442. 数组中重复的数据
class Solution:
def findDuplicates(self, nums: List[int]) -> List[int]:
ans=[]
for i in range(len(nums)):
while(nums[i]!=nums[nums[i]-1]):
nums[nums[i]-1],nums[i]=nums[i],nums[nums[i]-1]
for i ,v in enumerate(nums):
if i!=v-1:
ans.append(v)
return ans
380. O(1) 时间插入、删除和获取随机元素
# 实现RandomizedSet 类:
# RandomizedSet() 初始化 RandomizedSet 对象
# bool insert(int val) 当元素 val 不存在时,向集合中插入该项,并返回 true ;否则,返回 false 。
# bool remove(int val) 当元素 val 存在时,从集合中移除该项,并返回 true ;否则,返回 false 。
# int getRandom() 随机返回现有集合中的一项(测试用例保证调用此方法时集合中至少存在一个元素)。每个元素应该有 相同的概率 被返回。
# 你必须实现类的所有函数,并满足每个函数的 平均 时间复杂度为 O(1) 。
class RandomizedSet:
def __init__(self):
self.val_index={}
self.vals=[]
def insert(self, val: int) -> bool:
if(val in self.val_index):
return False
else:
self.vals.append(val)
self.val_index[val]=len(self.vals)
return True
def remove(self, val: int) -> bool:
if val in self.val_index:
index=self.val_index[val]
self.val_index[self.vals[-1]]=index
self.vals[index-1]=self.vals[-1]
self.vals.pop()
self.val_index.pop(val)
return True
else:
return False
def getRandom(self) -> int:
import random
num=random.choice(self.vals)
return num
# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()
26. 删除排序数组中的重复项
# 26. 删除有序数组中的重复项
# 给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
#
# 由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
#
# 将最终结果插入 nums 的前 k 个位置后返回 k 。
#
# 不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
l,r,n=0,0,len(nums)
while(r<n):
while(nums[l]==nums[r]):
r+=1
nums[l+1]=nums[r]
l+=1
return l+1
面试题 16.16. 部分排序
# 面试题 16.16. 部分排序
# 给定一个整数数组,编写一个函数,找出索引m和n,只要将索引区间[m,n]的元素排好序,整个数组就是有序的。注意:n-m尽量最小,也就是说,找出符合条件的最短序列。函数返回值为[m,n],若不存在这样的m和n(例如整个数组是有序的),请返回[-1,-1]。
# 输入: [1,2,4,7,10,11,7,12,6,7,16,18,19]
# 输出: [3,9]
from typing import List
class Solution:
def subSort(self, array: List[int]) -> List[int]:
if len(array)<2:
return [-1,-1]
l,r=1,len(array)-1
while(l<len(array) and array[l-1]<=array[l]):
l+=1
if(l==len(array)):
return [-1,-1]
while(array[r]>array[l-1] and array[r]>=array[r-1] ):
r-=1
# print(l-1,r+1)
l,r=l-1,r+1 #满足条件的节点为[0,l-1],[r+1,len(array)-1]
min_i,max_i = l+1,r-1
for i in range(l , r):
if (array[min_i] >= array[i]):
min_i = i
if (array[max_i] <= array[i]):
max_i = i
# print('&',array[min_i],array[max_i],'#',min_i,max_i,l,r)
while(r<len(array) and array[max_i]>array[r]):
r+=1
while(l>=0 and array[min_i]<array[l]):
l-=1
return [l+1,r-1]
a=[1,2,4,7,10,11,7,12,6,7,16,18,19]
# a=[1,3,5,7,9]
print(len(a))
s=Solution()
r=s.subSort(a)
print(r)
16. 最接近的三数之和
# 16. 最接近的三数之和
# 给你一个长度为n的整数数组nums和一个目标值target。请你从nums中选出三个整数,使它们的和与target最接近。返回这三个数的和。
from typing import List
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums.sort()
closest=sum(nums[0:3])
for i in range(len(nums)):
if(i>0 and nums[i-1]==nums[i]):
continue
l,r=i+1,len(nums)-1
while(l<r):
total=nums[i]+nums[l]+nums[r]
if abs(closest-target)>abs(total-target):
closest=total
if(total==target):
return closest
elif(total>target):
r-=1
while (l<r and nums[r]==nums[r+1]):
r-=1
else:
l+=1
while (l < r and nums[l] == nums[l-1]):
l+=1
return closest
1208. 尽可能使字符串相等
# 1208. 尽可能使字符串相等
# 给你两个长度相同的字符串,s 和 t。
# 将 s中的第i个字符变到t中的第 i 个字符需要|s[i] - t[i]|的开销(开销可能为 0),也就是两个字符的 ASCII 码值的差的绝对值。
# 用于变更字符串的最大预算是maxCost。在转化字符串时,总开销应当小于等于该预算,这也意味着字符串的转化可能是不完全的。
# 如果你可以将 s 的子字符串转化为它在 t 中对应的子字符串,则返回可以转化的最大长度。
# 如果 s 中没有子字符串可以转化成 t 中对应的子字符串,则返回 0。
#
# 输入:s = "abcd", t = "bcdf", maxCost = 3
# 输出:3
# 解释:s 中的 "abc" 可以变为 "bcd"。开销为 3,所以最大长度为 3。
class Solution:
def equalSubstring(self, s: str, t: str, maxCost: int) -> int:
a=[]
for i in range(len(s)):
a.append(abs(ord(s[i])-ord(t[i])))
l,r=0,0
tol=0
ans=0
while(r<len(a)):
tol+=a[r]
r+=1
if(tol>maxCost):
tol-=a[l]
l+=1
ans=max(ans,r-l)
return ans
1122. 数组的相对排序
# 1122. 数组的相对排序
# 给你两个数组,arr1 和arr2,arr2中的元素各不相同,arr2 中的每个元素都出现在arr1中。
# 对 arr1中的元素进行排序,使 arr1 中项的相对顺序和arr2中的相对顺序相同。未在arr2中出现过的元素需要按照升序放在arr1的末尾。
# 输入:arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6]
# 输出:[2,2,2,1,4,3,3,9,6,7,19]
from typing import List
class Solution:
def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
h,t={},[]
for num in arr2:
h[num]=0
for i in range(len(arr1)-1,-1,-1):
if arr1[i] in h:
h[arr1[i]]+=1
else:
t.append(arr1[i])
p=0
for num in arr2:
for q in range(h[num]):
arr1[p]=num
p+=1
t.sort()
for num in t:
arr1[p]=num
p+=1
return arr1
arr1 = [2,3,1,3,2,4,6,7,9,2,19]
arr2 = [2,1,4,3,9,6]
s=Solution()
r=s.relativeSortArray(arr1,arr2)
print(r)
57. 插入区间
# 57. 插入区间
# 给你一个 无重叠的 ,按照区间起始端点排序的区间列表。
# 在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)
# 输入:intervals = [[1,3],[6,9]], newInterval = [2,5]
# 输出:[[1,5],[6,9]]
from typing import List
class Solution:
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
intervals.append(newInterval)
if len(intervals)<=1:
return intervals
intervals.sort(key=lambda x:x[0])
res=[intervals[0]]
for i in range(len(intervals)):
if res[-1][1]>=intervals[i][0]:
res[-1][1]=max(res[-1][1],intervals[i][1])
else:
res.append(intervals[i])
return res
18. 四数之和
class Solution:
# def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
def fourSum(self, nums, target) :
nums.sort()
ans=[]
n=len(nums)
for i in range(n-3):
if i>0 and nums[i-1]==nums[i]:
continue
if nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target:
break
if nums[i]+nums[n-1]+nums[n-2]+nums[n-3]<target:
continue
for j in range(i+1,n-2):
if j > i+1 and nums[j - 1] == nums[j]:
continue
if nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target:
break
if nums[i] + nums[j] + nums[n - 1] + nums[n - 2] < target:
continue
l,r=j+1,n-1
while(l<r):
# print(nums)
total=nums[i]+nums[j]+nums[l]+nums[r]
# print(i,j,l,r,total)
if(total==target):
ans.append([nums[i], nums[j], nums[l], nums[r]])
while(l<r and nums[l]==nums[l+1]):
l+=1
l+=1
while(l<r and nums[r]==nums[r-1]):
r-=1
r-=1
elif(total>target):
r-=1
else:
l+=1
return ans
1539. 第 k 个缺失的正整数
# 1539. 第 k 个缺失的正整数
# 给你一个 严格升序排列 的正整数数组 arr 和一个整数 k 。
#
# 请你找到这个数组里第 k 个缺失的正整数。
#
# 输入:arr = [2,3,4,7,11], k = 5
# 输出:9
# 解释:缺失的正整数包括 [1,5,6,8,9,10,12,13,...] 。第 5 个缺失的正整数为 9 。
class Solution:
# def findKthPositive(self, arr: List[int], k: int) -> int:
def findKthPositive(self, arr, k) :
cnt = 0
ans = -1
num=1
i=0
while(cnt<k):
if(i<len(arr) and arr[i]==num):
i+=1
else:
cnt+=1
if(cnt==k):
break
num+=1
ans=num
return ans
s=Solution()
nums=[2,3,4,7,11]
k=5
# nums=[1,2]
# k=1
r=s.findKthPositive(nums,k)
print(r)
268. 缺失数字
# 268. 丢失的数字
# 给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。
# 输入:nums = [3,0,1]
# 输出:2
# 解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。
from typing import List
class Solution:
def missingNumber(self, nums: List[int]) -> int:
h={}
for i in nums:
h[i]=1
for i in range(len(nums)+1):
if i not in h:
return i
return -1
# 位运算方法,异或
from typing import List
class Solution:
def missingNumber(self, nums: List[int]) -> int:
num=0
for i in nums:
num^=i
for i in range(len(nums)+1):
num^=i
return num