算法入门_day02

这篇博客探讨了如何使用双指针法解决两个经典的数组操作问题:有序数组的平方排序和轮转数组。在有序数组的平方问题中,通过双指针从两端开始比较并填充结果数组,确保了非递减的顺序。而在轮转数组问题中,通过两次反转实现了原地旋转,解决了空间复杂度的要求。这两个问题都展示了双指针在数组操作中的高效性和灵活性。
摘要由CSDN通过智能技术生成

双指针

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)

方法二:

方法三:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pythonistas29xs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值