75、颜色分类,有三种值0、1、2需要将他们排序
思路与快排类似,用zero,two记录0、2的下标,使用i遍历数组,当找到0/2时将i与对应下标的nums交换
class Solution:
def sortColors(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
def swap(nums,index1,index2):
nums[index1],nums[index2]=nums[index2],nums[index1]
n=len(nums)
if n <2:
return
zero = 0
two = n
i = 0
while i<two:
if nums[i]==0:
swap(nums, i, zero)
i+=1
zero+=1
elif nums[i]==1:
i+=1
else:
two-=1
swap(nums, i, two)
return nums
88、合并有序数组
由于给出的是两个有序数组,在为结果数组添加数字的时候直接比较两个数组的最后一位即可插入数组。
详细思路参考:
作者:灵茶山艾府 链接:https://leetcode.cn/problems/merge-sorted-array/solutions/2385610/dao-xu-shuang-zhi-zhen-wei-shi-yao-dao-x-xxkp/ 来源:力扣
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
p1, p2, p = m - 1, n - 1, m + n - 1
while p2 >= 0: # nums2 还有要合并的元素
# 如果 p1 < 0,那么走 else 分支,把 nums2 合并到 nums1 中
if p1 >= 0 and nums1[p1] > nums2[p2]:
nums1[p] = nums1[p1] # 填入 nums1[p1]
p1 -= 1
else:
nums1[p] = nums2[p2] # 填入 nums2[p1]
p2 -= 1
p -= 1 # 下一个要填入的位置
LCR 170、交易逆序对的总数
使用分治算法,将数组切分,在每次和并的时候统计当前左数组和右数组之间逆序对的数量。
详解见链接
class Solution:
def reversePairs(self, record: List[int]) -> int:
def merge_sort(l, r):
# 终止条件
if l >= r: return 0
# 递归划分
m = (l + r) // 2
res = merge_sort(l, m) + merge_sort(m + 1, r)
# 合并阶段
i, j = l, m + 1
tmp[l:r + 1] = record[l:r + 1]
for k in range(l, r + 1):
if i == m + 1:
record[k] = tmp[j]
j += 1
elif j == r + 1 or tmp[i] <= tmp[j]:
record[k] = tmp[i]
i += 1
else:
record[k] = tmp[j]
j += 1
res += m - i + 1 # 统计逆序对
return res
tmp = [0] * len(record)
return merge_sort(0, len(record) - 1)
作者:Krahets
链接:https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof/solutions/622496/jian-zhi-offer-51-shu-zu-zhong-de-ni-xu-pvn2h/
215、数组前k个最大的数
题目要求时间复杂度在O(n),使用了分治排序通过了。
以下是提交的代码:
class Solution:
def findKthLargest(self, nums: list[int], k: int) -> int:
n=len(nums)-1
def mergesort(l,r):
if l>=r:
return 0
m=(l+r)//2
mergesort(l,m)
mergesort(m+1,r)
i,j=l,m+1
tmp[l:r+1]=nums[l:r+1]
for k in range(l,r+1):
if i==m+1 :
nums[k]=tmp[j]
j+=1
elif j==r+1 or tmp[i]<=tmp[j]:
nums[k]=tmp[i]
i+=1
else:
nums[k]=tmp[j]
j+=1
return 0
tmp=[0]*len(nums)
mergesort(0,n)
ans=0
for i in range(n,-1,-1):
ans+=1
if ans==k :
return nums[i]
有个疑问是 for k 循环语句里的条件判断,如果写成
for k in range(l,r+1):
if i==m+1 or tmp[i]>=tmp[j]:
nums[k]=tmp[j]
j+=1
else:
nums[k]=tmp[i]
i+=1
会显示出错,超出了数组的索引
需要将判断条件改成if i==m+1 or (j<=r and tmp[j]<tmp[i]) :
面试题 17.14 最小k个数
思路与上一题类似
class Solution:
def smallestK(self, arr: List[int], k: int) -> List[int]:
n=len(arr)-1
temp=[0]*(n+1)
def mergesort(l,r):
if l>=r:
return 0
m=(l+r)//2
mergesort(l,m)
mergesort(m+1,r)
i,j=l,m+1
temp[l:r+1]=arr[l:r+1]
for k in range(l,r+1):
if i==m+1 or (j<=r and temp[j]<=temp[i]):
arr[k]=temp[j]
j+=1
else:
arr[k]=temp[i]
i+=1
return arr
arr=mergesort(0,n)
result=[]
for i in range(k):
result.append(arr[i])
return result
1122、数组的相对排序
需要注意字典的处理
class Solution:
def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
n1,n2=len(arr1),len(arr2)
dic={}
new_arr=[]
result=[]
for num in arr1:
if num in arr2:
if num in dic:
dic[num]+=1
else:
dic[num]=1
else:
new_arr.append(num)
for num in arr2:
result=result+[num]*dic[num]
new_arr.sort()
return result+new_arr
220、存在重复元素3
需要在数组中查找窗口为indexDiff的子数组中是否有两个数的差的绝对值<=valueDiff
在思考的时候想到查找窗口这么回事,但是想不到如何处理其中的数,因为按暴力遍历的话会超时。看了题解后才想得到如何使用桶排序。使用字典进行存储,原数组的数按照大小分配到不同的桶:nth=nums[i]//(valueDiff+1),这样子只有同一个或相邻的桶中的数值满足差的绝对值的约束。
最后要记得保持窗口的长度为indexDiff+1
class Solution:
def containsNearbyAlmostDuplicate(self, nums: List[int], indexDiff: int, valueDiff: int) -> bool:
bucket=dict()
for i in range(len(nums)):
nth=nums[i]//(valueDiff+1)
if nth in bucket:
return True
if nth-1 in bucket and abs(nums[i]-bucket[nth-1])<=valueDiff:
return True
if nth+1 in bucket and abs(nums[i]-bucket[nth+1])<=valueDiff:
return True
bucket[nth]=nums[i]
if i>=indexDiff:
bucket.pop(nums[i-indexDiff]//(valueDiff+1))
return False
164、最大间距
想用桶排序,,被击穿了。