双指针
977. 有序数组的平方
https://leetcode.cn/problems/squares-of-a-sorted-array/
数组 双指针 排序
给你一个按
非递减顺序
排序的整数数组nums
,返回每个数字的平方
组成的新数组,要求也按非递减顺序
排序。
方法一:暴力排序
方法二:双指针法
代码随想录思路:逆向思维 (官方解法-方法三:双指针)
数组其实是有序的, 只不过负数平方之后可能成为最大数了。
那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
此时可以考虑双指针法了, i i i指向起始位置, j j j指向终止位置。
定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
如果
A
[
i
]
∗
A
[
i
]
<
A
[
j
]
∗
A
[
j
]
A[i] * A[i] < A[j] * A[j]
A[i]∗A[i]<A[j]∗A[j],那么
r
e
s
u
l
t
[
k
]
=
A
[
j
]
∗
A
[
j
]
result[k] = A[j] * A[j]
result[k]=A[j]∗A[j]
如果
A
[
i
]
∗
A
[
i
]
>
=
A
[
j
]
∗
A
[
j
]
A[i] * A[i] >= A[j] * A[j]
A[i]∗A[i]>=A[j]∗A[j],那么
r
e
s
u
l
t
[
k
]
=
A
[
i
]
∗
A
[
i
]
result[k] = A[i] * A[i]
result[k]=A[i]∗A[i]
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
# 双指针法
n = len(nums)
left, right, k = 0, n - 1, n - 1
result = [0] * n
while left <= right:
if nums[left] * nums[left] > nums[right] * nums[right]:
result[k] = nums[left] * nums[left]
left += 1
else:
result[k] = nums[right] * nums[right]
right -= 1
k -= 1
return result
复杂度分析
时间复杂度:
O
(
n
)
O(n)
O(n),其中 n 是数组
nums
\textit{nums}
nums 的长度。
空间复杂度:
O
(
1
)
O(1)
O(1)。除了存储答案的数组以外,我们只需要维护常量空间。
189.轮转数组
https://leetcode.cn/problems/rotate-array/
数组 数学 双指针
给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
原地算法
方法一:先反转整个数组,再反转局部区间
本题是右旋转,其实就是反转的顺序改动一下,优先反转整个数组,步骤如下:
- 反转整个数组
- 反转区间为前k的数组
- 反转区间为k到末尾的数组
这是一个重要的思想,可以用到很多需要反转的题目中。
注:本题还有一个小陷阱,题目输入中,如果k大于nums.size了应该怎么办?
例如,1,2,3,4,5,6,7 如果右移动15次的话,是 7 1 2 3 4 5 6 。
所以其实就是右移 k % nums.size() 次,即:15 % 7 = 1
复杂度分析
时间复杂度:
O
(
n
)
O(n)
O(n),其中 n 为数组的长度。每个元素被翻转两次,一共 n 个元素,因此总时间复杂度为
O
(
2
n
)
=
O
(
n
)
O(2n)=O(n)
O(2n)=O(n)。
空间复杂度:
O
(
1
)
O(1)
O(1)。