旋转数组
给定一个数组, 将数组中的元素向右移动 K 个位置, 其中 K 是非负数.
示例:
输入: [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]
说明:
尽可能想出更多的解决方案, 至少有三种不同的方法可以解决这个问题.
要求使用空间复杂度为 O(1) 的原地算法.
个人理解:
数组的旋转, 即把一个数组最开始的若干个元素搬到数组的末尾.
所以我们按照字面意思, 来改变数组下标, 每次让最后一位数值和前一位数值交换, 然后再将最后一位数值赋值为第一位数值, 让数组排序.
举个栗子
每旋转一次的执行过程
1) 先将最后一个保存到临时变量
1 2 3 4 5 6 7 8 [8] --- 临时变量
2) 位移
_ 1 2 3 4 5 6 7 [8] --- 临时变量
3) 将临时变量放到第一个
8 1 2 3 4 5 6 7
代码如下:
- public class Rotate {
- public static void rotate(int[] nums, int k) {
- if (nums == null || k == 0 || k == nums.length) {
- return ;
- }
- // 空间复杂度为 O(1)
- int temp = 0;
- while (k> 0) {
- // 每次将最后一位和前一位数值交换
- temp = nums[nums.length - 1];
- for (int i = nums.length -2; i>= 0; i--) {
- nums[i+1] = nums[i];
- }
- // 每次将最后一位赋值为第一个
- nums[0] = temp;
- k--;
- }
- for (int num : nums) {
- System.out.print(num + ",");
- }
- }
- public static void main(String[] args) {
- int[] nums = {-1, -100, 3, 99};
- int k = 2;
- rotate(nums, k);
- }
- }
这样子虽然简单, 但是在 leecode 提交却提示超出时间限制... 看一下时间复杂度确实也是, 我们的时间复杂度达到了 O(kn) . 确实太大了 .....((/- -)/
然后自己去网上搜了一下其他回答, 贴个老哥的代码在这里, 我看的不是很懂, 用到的思想是取余翻转.
- class Solution {
- public static void rotate(int[] nums, int k) {
- if (nums == null || k == 0 || k == nums.length) {
- return;
- }
- k = k % nums.length;
- reverse(nums, 0, nums.length - k - 1);
- reverse(nums, nums.length - k, nums.length - 1);
- reverse(nums, 0, nums.length - 1);
- }
- private static void reverse(int[] nums, int start, int end) {
- while (start < end) {
- int temp = nums[start];
- nums[start] = nums[end];
- nums[end] = temp;
- start++;
- end--;
- }
- }
- }
这里的时间复杂度为 O(n), 比原来的 O(kn) 好, 执行效率高了挺多.
来源: http://www.jianshu.com/p/5b1d30a56281