旋转数组
将包含 n 个元素的数组向右旋转 k 步。
例如,如果 n = 7 , k = 3,给定数组 [1,2,3,4,5,6,7]
,向右旋转后的结果为 [5,6,7,1,2,3,4]
。
注意:
尽可能找到更多的解决方案,这里最少有三种不同的方法解决这个问题。
感觉这个题目还是可以的。
首先要明白什么是一维数组向右旋转几步(当然肯定会有对应向左旋转几步喽,说不定也有向上或者向下旋转啦,呵呵自己google了),你以为是像上学时候那样军训时原地旋转吗?其实我在很久以前刚触到的时候就是这么想的,我厉害吧。
码子可以说明一切:
-
[1,2,3,4,5,6,7]//初始数组
-
//向右旋转1步
-
[7,1,2,3,4,5,6]//向右旋转1步之后的数组
-
//再向右旋转1步,相对一最开始的数组就是向右旋转2步
-
[6,7,1,2,3,4,5]//向右旋转2步之后的数组
-
//把最原始的数组向左旋转1步
-
[2,3,4,5,6,7,1]//这就是向左旋转一步之后的数组
应该看明白了吧,就拿向右旋转1步来说:首先向拿旋转的数组要有一个初始的数组,是相对于一个数组来说向左或者向右的;向右旋转1步就是说把初始数组的最高位上的数字放置在数组的最低位置,让后其他位置上的数字都把自身的位置提高1位。就这么简单什么向左旋转都一个道理(程序员都爱说一些高大上的名词。听起来很牛逼,说穿了哎。。。)
其实这就很容易想到第一种方案:
-
private static int[] Rotate2(int[] nums, int k)//k就是指旋转几步
-
{
-
int length = nums.Length;
-
while (k > 0)//循环几次就看k是多少
-
{
-
int t = 0;
-
t = nums[length - 1];//这是获取数组最高位置上的数字
-
for (int j = length - 2; j >= 0; j--)//从倒数第二个数字开始,倒叙循环。循环主要目的就是把其他数字位置都抬高一位
-
{
-
nums[j + 1] = nums[j];
-
}
-
nums[0] = t;//抬高玩其他的,就可以直接把最高位上的数字赋值到0号位上了
-
k--;//完成一个循环
-
}
-
return null;
-
}
其实上面每一次循环就三步:第一获取最高位的数字,第二把其他位上的数字都抬高一位,第三把最初获得最高位的数字赋值到最低位置上。
第二种方法就比较取巧了:
-
private static int[] Rotate1(int[] nums, int k)
-
{
-
int[] result = new int[nums.Length];//根据nums数组长度生成和其一样长度的数组
-
for (int i = 0; i < nums.Length; i++)
-
{
-
result[(i + k) % nums.Length] = nums[i];//这里用到了取余,也是这个方法的核心
-
}
-
return result;
-
}
为什么用取余上个例子:
-
///3元素在数组中的2位置上,(2+3) % 7 = 5
-
///5元素在数组中的4位置上,(4+3) % 7 = 0
-
///6元素在数组中的5位置上,(5+3) % 7 = 1
-
///7元素在数组中的6位置上,(6+3) % 7 = 2
长度为7的数组,向右旋转3步,数字的位置加3之后大于7的都要再从0号位置重新开始计算剩余的步子。这点特性就可以很好的用到求余。