轮转数组
给定一个整数数组 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个位置。(我说的有些乱,凑合看吧)