题目链接如下:
88. 合并两个有序数组https://leetcode.cn/problems/merge-sorted-array/
方法总结:
(1)切片合并+排序
(2)双指针+比较大小,正向(按从小到大)/逆向(按从大到小)插入
读题,最简单的思路是合并数组后排序,这种方法速度和效率也比较高。参见解法1:
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.
"""
#使用切片建立新的数组
nums1[:]=nums1[:m]+nums2[:n]
#print(nums1)
nums1.sort()
写了个快排,不过明显比内置sort函数慢。。空间占用大很多,可以忽略。
【这里个人复习一下class类中函数相互调用的方法,一定要记得函数定义时候加上“self”,并且在相互调用的时候也使用self.defxx,否则会报错“nameXX not defined”】
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.
"""
#使用切片建立新的数组
nums1[:]=nums1[:m]+nums2[:n]
#print(nums1)
#nums1.sort()#python内置sort函数
self.quicksort(nums1,0,len(nums1)-1)
def quicksort(self, nums: List[int],start:int,end:int):#自定义快速排序
if start>=end:#开始位置小于结束位置,就返回一次排序
return
left,right=start,end
base=nums[start]#选定一个初始默认base
while left<right:
while nums[right]>=base and left<right:
right-=1
nums[left]=nums[right]
while nums[left]<=base and left<right:
left+=1
nums[right]=nums[left]
nums[left]=base
self.quicksort(nums,start,left-1)#每次排序后的base处的索引-left之前排序
self.quicksort(nums,left+1,end)#每次排序后的base处的索引-left之后排序
利用了两个数组都“分别为排序好的数组”,通过【双指针】直接比较大小,还可以这么写:
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.
"""
i,j=0,0#定义初始指针
new=[]
#m=3,len(nums)=6
while i<m or j<n:
if i==m:#nums1中最后一位小于nums2中未排完的数
new.append(nums2[j])
j+=1
elif j==n:#nums2中最后一位小于nums1中未排完的数
new.append(nums1[i])
i+=1
elif nums1[i]<=nums2[j]:
new.append(nums1[i])
i+=1
elif nums1[i]>nums2[j]:
new.append(nums2[j])
j+=1
#print(j)
nums1[:]=new
但是上述方法需要开辟新的内存空间(防止新数据覆盖旧数据),那么可以考虑逆向思维,因为nums1是足够长的(m+n长度),逆双指针从尾部开始更新:
这种方法不会覆盖,因为极限情况,假如nums2全部排到尾部,那么也正好填充满,而假如nums1中有数值排到尾部,那么前面的空则+1,更大于nums2,而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.
"""
#无需开辟新的空间,从后往前,从大到小进行更新
i,j=m-1,n-1
tail=m+n-1
while i>=0 or j>=0:
if i==-1:#当原m个nums1数组中都已排完,tail也已经到相应位置
nums1[tail]=nums2[j]
j-=1
elif j==-1:
nums1[tail]=nums1[i]
i-=1
elif nums1[i]>=nums2[j]:
nums1[tail]=nums1[i]
i-=1
elif nums2[j]>nums1[i]:
nums1[tail]=nums2[j]
j-=1
tail-=1
可以看到,这种方法明显速度高很多。