轮转数组(leetcode)

难度:中等

题目描述

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]解释:
向右轮转 1 步: [7,1,2,3,4,5,6]向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

思路

这道题是目前做过用时最长的一道题了!改了二十来次代码才通过。一定要注意使用for循环时有没有越界,以及有没有超时。这道题有一个需要注意的点是向右轮转,不要看错或想错了(比如我的第一个代码写成了向左轮转),还有一个可以简化的地方:看k的值,使用k%n简化k值(n为数组元素个数),因为当元素个数为7时,向右轮转一个位置与向右轮转八个位置得到的结果是一样的,我们可以用这种思路控制k的大小。

可以使用额外数组,定义一个新的数组。对于前k%n个元素,新的数组前k%n个元素可以被覆盖为原数组的元素:新数组第i个元素被覆盖为原数组第i+n-k%n个元素,很好理解,对于n=7,k=4的情况,new[0]=old[3],new[1]=old[4],new[2]=old[5],new[3]=old[6]。对于后面剩余元素,新数组第i个元素被覆盖为原数组的第i-k%n个元素,对于n=7,k=4的情况,new[4]=old[0],new[5]=old[1]......

代码

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n=nums.size();
        int m=k%n;
        vector<int> nums1(n);
        for(int i=0;i<m;i++){
            nums1[i]=nums[i+n-m];
        }
        for(int i=m;i<n;i++){
            nums1[i]=nums[i-m];
        }
        nums=nums1;
    }
};

复杂度

  • 时间复杂度: O(n)。

  • 空间复杂度: O(n)。

### LeetCode 数组题目及其解法 #### 移除元素 在解决移除特定值的问题时,可以采用双指针方法来优化效率。通过设置两个指针`slow`和`fast`,其中`fast`用于遍历整个数组寻找不等于目标值的元素,而`slow`则用来记录新数组的有效部分[^2]。 ```cpp class Solution { public: int removeElement(vector<int>& nums, int val) { int slow = 0; for (int fast = 0; fast < nums.size(); ++fast) { if (nums[fast] != val) { nums[slow++] = nums[fast]; } } return slow; } }; ``` 此算法的时间复杂度为O(n),空间复杂度为O(1)。 #### 查找第一个和最后一个位置 当需要在一个已排序的数组中找到某个指定元素第一次出现和最后一次出现的位置时,可以通过两次二分查找分别定位这两个边界。每次二分查找都遵循标准流程,在满足条件的情况下调整左右边界直至收敛到确切位置[^1]。 #### 螺旋矩阵 对于螺旋顺序打印二维矩阵的问题,核心在于控制四个方向上的移动界限,并随着每一轮内圈缩小不断更新这些界限直到完成遍历全部元素[^5]。 #### 处理只读数组中的重复项 针对不允许修改原数组且需找出唯一重复数的情况,可利用Floyd判圈算法(龟兔赛跑),先让快慢指针相遇再重置其中一个重新同步前进最终交汇于起点即为所求重复值所在索引处[^3]。 #### 求长度最小子数组 为了计算连续子序列之和大于给定阈值所需的最短长度,滑动窗口技术提供了高效解决方案。维持一对动态变化的端点形成窗口并实时监测其内部总和是否符合条件,一旦达成立即尝试收缩左侧边沿以探索更优解的可能性[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值