Leetcode 977 有序数组的平方
题目描述:
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
示例 2:
输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]
解法1:
#直接排序
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
return sorted(num * num for num in nums)
这是最简单,代码量最少的一种解法,直接将nums中的数平方后直接排序。但是没有用到这一条件:给定的数组是按照非递减顺序。
解法2:
#双指针
lass Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
n=len(nums)
ans=[0]*n
i,j,pos=0,n-1,n-1
while i<=j:
if nums[i]*nums[i]>nums[j]*nums[j]:
ans[pos]=nums[i]*nums[i]
i+=1
else:
ans[pos]=nums[j]*nums[j]
j-=1
pos-=1
return ans
可以使用双指针分别指向0,n-1,每次比较两个指针对应的数,选择较大的那个逆序(或者选择较小的那个顺序也行)放入答案并移动指针,同时,这种方法也无需处理某一指针移动至边界的情况。
解法3(超时?):
#双指针、归并排序
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
n = len(nums)
negative = -1
#python的变量不用声明,i,num用于记录python内置函数
#enumerate的返回,即列表nums的下标和下标对应的数值
for i, num in enumerate(nums):
if num<0:
negative=i
else:
break
ans=list()
#nums[0]到nums[i]均为负数
#nums[j]到nums[n-1]均为正数
i,j=negative,negative+1
#当指针移至边界时,将另一指针还未遍历到的数依次放入答案
while i>=0 or j<n:
if i<0:
ans.append(nums[j]*nums[j])
elif j==n:
ans.append(nums[i]*nums[i])
i-=1
#归并排序
elif nums[i]*nums[i]<nums[j]*nums[j]:
ans.append(nums[i]*nums[i])
i-=1
else:
ans.append(nums[j]*nums[j])
j+=1
return ans
解法1没有利用(数组nums已经按照升序排序)这个条件,显然,如果数组nums中的所有数都是非负数,那么将每个数平方之后,数组仍然保持升序;如果数组nums中的所有数都是负数,那么将每个数平方之后,数组仍然保持降序。
这样一来,如果我们能够找到数组nums中负数与非负数的分界线,那么就可以用类似归并排序的方法,具体的,我们可以设置一个变量negative,作为负数与非负数的分界线,也就是说,nums[0]到nums[negative]均为负数,nums[negative+1]到num[n-1]均为非负数。当我们对数组中的数进行平方操作后,那么nums[0]到nums[negative]单调递减,nums[negative+1]到nums[n-1]单调递增。
由于我们已经得到了两个已经有序的子数组,因此就可以使用归并的方法进行排序。具体地,使用两个指针分别指向negative和negative+1,每次比较两个指针对用的数,选择较小的那个放入答案并移动指针,当某一指针移至边界时,将另一指针还未遍历到的数依次放入答案。