189.轮转数组

轮转数组

给定一个整数数组 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]

示例 2:

输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]

方法1:分块拼接法(我瞎起的)

这道题不要被表象欺骗,看起来是将数组转了个圈,但是我们还能发现其他规律,观察示例1:nums = [1,2,3,4,5,6,7], k = 3输出: [5,6,7,1,2,3,4],我们发现元素str1[1,2,3,4]和str2[5,6,7]的内部顺序并没有发生改变,但是str1和str2之间的顺序被前后调换了一下,基于这个规律,我们就不用考虑转圈的问题了。那么是切断元素的呢??这个就和入参k有关了,观察前边的元素,盯住元素1的位置,它由下标0,向右移动了三个位置,变为下标3;住元素2的位置,它由下标1,向右移动了三个位置,变为下标4;既然他们向后移动了,靠后的元素必然就被挤走了,挤走了谁呢?由于移动了三个元素,所以到最后,元素2顶替了元素5,元素3顶替了元素6,元素4顶替了元素7,导致后边的三个元素5,6,7只能去最前边了,所以我们发现,将整个数组分成两截的主要元凶是k值,决定截断位置的要素是k的大小,截断方法是原数组从后向前数k个值,这k个值就是要移到最前边的,并且这k个值的先后顺序不会变,依旧是[5,6,7]。
class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> v1,v2; //声明v1
        k = k % n;
        v1.assign(nums.end()-k, nums.end());//取后边k个值给v1
        v2.assign(nums.begin(), nums.end()-k);//取前边n-k个值给v2
        v1.insert(v1.end(),v2.begin(),v2.end());//v1与v2拼接到v1身上
        nums=v1;//v1赋值给nums
    }
};

这个方法的缺点就是耗内存,因为又建立了俩数组,但是俗话说的好:这年头内存不值钱!嘿嘿

方法2:咔咔翻转法

上一个不需要额外空间的方法:继续观察找规律,示例1:nums = [1,2,3,4,5,6,7], k = 3输出: [5,6,7,1,2,3,4],结合方法一,将两段子数组调换了一下顺序,那么我要是先将整个数组调换一下,是不是感觉前边要转移的数就到后边了,后边的也来前边了,[7,6,5,4,3,2,1],还是差点意思啊,我想要5,6,7不要765,想要1,2,3,4,所以目前来看差什么?再把这个小区间反转一下是不就行了,分别只反转前k个和后n-k个元素就是最终结果了。
class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        k = k % n;
        // 第一步:整体反转数组
        reverse(nums.begin(), nums.end());
        // 第二步:反转前 k 个元素
        reverse(nums.begin(), nums.begin() + k);
        // 第三步:反转后 n-k 个元素
        reverse(nums.begin() + k, nums.end());
    }
};

方法3:挨个转圈法

这个方法是我最初想到的,但是当case数据非常庞大时就要老命了,咔咔超时,希望有缘人帮我在此基础上给点建议吧,我不想思考了。🌚

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

关于那个k = k % n是不是有人蒙了啊,咋还吧人家值给变了,那咋能行呢?%是取余的,都知道哈,假设n=8,当k小于8时,余数就是k本身,当k=n时,余数为0,嘶,k=0?数组不用转?没错啊,k等于n的话移动后每个元素又回到自己位置了,那不就是白溜达嘛。当k>n,k<2n时,其实是k走了一圈后又多走了n-k个位置,也就是k%n,那么当k更大时,其实一样的,反复转几圈后再走k%n个位置,其实就是走了k%n个位置。(我说的有些乱,凑合看吧)

你,学废了吗???

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值