设计一个算法,把一个含有N个元素的数组循环右移K位,要求时间复杂度为O(N),且只允许使用两个附加变量。

不合题意的解法如下:

我们先试验简单的办法,可以每次将数组中的元素右移一位,循环K次。abcd1234→4abcd123→34abcd12→234abcd1→1234abcd。伪代码如下:

RightShift(int* arr, int N, int K)
{while(K--){int t = arr[N - 1];for(int i = N - 1; i > 0; i --)arr[i] = arr[i - 1];arr[0] = t;}
}

虽然这个算法可以实现数组的循环右移,但是算法复杂度为 O ( K  *  N ),不符合题目的要求,需要继续往下探索。

分析与解法

【一步分析法】:

假如数组为abcd1234,循环右移4位的话,我们希望到达的状态是1234abcd。不妨设K是一个非负的整数,当K为负整数的时候,右移K位,相当于左移(-K)位。左移和右移在本质上是一样的。

【解法一】

大家开始可能会有这样的潜在假设,K<N。事实上,很多时候也的确是这样的。但严格地说,我们不能用这样的“惯性思维”来思考问题。尤其在编程的时候,全面地考虑问题是很重要的,K可能是一个远大于N的整数,在这个时候,上面的解法是需要改进的。

仔细观察循环右移的特点,不难发现:每个元素右移N位后都会回到自己的位置上。因此,如果K > N,右移K-N之后的数组序列跟右移K位的结果是一样的。进而可得出一条通用的规律:右移K位之后的情形,跟右移K’= K % N位之后的情形一样。

RightShift(int* arr, int N, int K)
{K %= N;while(K--){int t = arr[N - 1];for(int i = N - 1; i > 0; i --)arr[i] = arr[i - 1];arr[0] = t;}
}

可见,增加考虑循环右移的特点之后,算法复杂度降为O(N),这跟K无关,与题目的要求又接近了一步。但时间复杂度还不够低,接下来让我们继续挖掘循环右移前后,数组之间的关联。

【进一步分析法】----》推荐思路

假设原数组序列为abcd1234,要求变换成的数组序列为1234abcd,即循环右移了4位。比较之后,不难看出,其中有两段的顺序是不变的:1234和abcd,可把这两段看成两个整体。右移K位的过程就是把数组的两部分交换一下。变换的过程通过以下步骤完成:

1.   逆序排列abcd:abcd1234 → dcba1234;

2.   逆序排列1234:dcba1234 → dcba4321;

3.   全部逆序:dcba4321 → 1234abcd。

伪代码可以参考如下:

package TestMyselfe;
import java.util.Arrays;
public class Testcvte1 {public static int[] RightShift(int arr[],int n,int k){k %= n;Reverse(arr, 0, n-k - 1);//0与1交换Reverse(arr, n - k, n - 1);//2与3交换Reverse(arr, 0, k - 1);//0与1交换return arr;}public static void Reverse(int arr[], int b, int e){for(; b < e; b++, e--){int temp = arr[e];arr[e] = arr[b];arr[b] = temp;}}public static void main(String[] args) {int data[]={1,2,3,4};System.out.println("循环右移2位的结果:"+Arrays.toString(RightShift(data,4,2)));}
}

这样,我们就可以在线性时间内实现右移操作了。

【步步惊心】数组循环右移相关推荐

  1. 实验8.1 指针与数组 6-6 数组循环右移

    本题要求实现一个对数组进行循环右移的简单函数:一个数组a中存有n(>0)个整数,将每个整数循环向右移m(≥0)个位置. 函数接口定义: int ArrayShift( int a[], int ...

  2. PTA-6-1 数组循环右移 (20分)(C语言)

    函数接口定义: int ArrayShift( int a[], int n, int m ); 其中a[]是用户传入的数组:n是数组的大小:m是右移的位数.函数ArrayShift须将循环右移后的数 ...

  3. c语言将数组元素循环右移k位,把一个含有N个元素的数组循环右移K位

    普通解法: 可以每次将数组中的元素右移一位,循环K次.每个元素右移N位后都会回到自己的位置上.因此,如果K > N,右移K-N之后的数组序列跟右移K位的结果是一样的.进而可得出一条通用的规律:右 ...

  4. 数组:如何把一个数组循环右移K位

    问题描述: 假设要把数组12345678右移2位,变为78123456. 分析: 方法一: 比较移位前后数组序列的形式,不难看出,其中有两段序列的顺序是不变的,即就是 78 和 123456, 可以把 ...

  5. 每天一道LeetCode-----有序数组循环右移n位后,寻找最小值,数组中可能包含重复元素

    Find Minimum in Rotated Sorted Array II 原题链接Find Minimum in Rotated Sorted Array II 一个有序数组循环右移n位,找到右 ...

  6. 1008. 数组元素循环右移问题 (20)-PAT乙级真题

    一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M>=0)个位置,即将A中的数据由(A0 A1--AN-1)变换为(AN-M -- AN-1 A0 ...

  7. PAT 数组元素循环右移问题(转自柳神)

    一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M>=0)个位置,即将A中的数据由(A0 A1--AN-1)变换为(AN-M -- AN-1 A0 ...

  8. (C++)1008 数组元素循环右移问题

    #include<cstdio> //注意:不允许使用另外数组,序列结尾不能有多余空格,不能直接认为right<n //1.读入数组长度,和右移位数,读入数组 //2.未必要对实际数 ...

  9. Basic Level 1008. 数组元素循环右移问题 (20)

    一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M>=0)个位置,即将A中的数据由(A0 A1--AN-1)变换为(AN-M -- AN-1 A0 ...

最新文章

  1. linux avahi-daemon进程 网络服务 简介
  2. 鸟哥的Linux私房菜(基础学习,服务器架设)
  3. SQL盲注之时间注入
  4. 【BZOJ-3681】Arietta 网络流 + 线段树合并
  5. 每日程序C语言16-找出比赛对手名单
  6. 004-JQuery属性
  7. SHELL实战day12
  8. 汶川地震一加一援助计划倡议书
  9. python3 + selenium + (chrome and firefox)使用
  10. [Linux网络编程]以太网封装格式及相关结构体
  11. 动画学习android,Android动画学习
  12. 【三维路径规划】基于matlab粒子群算法无人机山地三维路径规划【含Matlab源码 1831期】
  13. 东北大学金工实习考试题库
  14. 计算机专业论文评定意见,毕业论文评定意见(级).doc
  15. 「为了孩子上海淀小学,我一周上七节课」
  16. 本地安装并创建MySQL数据库
  17. 圆桌问答 (2017 第一季)
  18. 电力系统谐波影响及治理
  19. Java架构-微信交流群
  20. python数学公式的输入

热门文章

  1. 几个简单代码片段-- Google C++ style guide
  2. 别让 Linux 成为拿offer的阻碍
  3. Ubuntu 12.04 双显卡安装(Nvidia+intel集成卡 --Optimus智能切换技术)
  4. python人工智能项目实例-Python在人工智能中的实例
  5. javascript实现毫秒级精准定时执行函数
  6. 注意力测试软件系统,学生自测:注意力操作性测试
  7. 带电圆环matlab,利用MATLAB分析圆环电流的磁场分布
  8. 基于GIS的校园公交车管理系统设计(西安电子科技大学GIS课程大作业)
  9. 数据带宽 总线带宽区别_如何减少数据量(和带宽)流服务的使用
  10. 基于多源信息和异构网络的circRNA与疾病关联关系预测