码迷,mamicode.com
首页 > 移动开发 > 详细

数组元素整体移动问题的研究

时间:2015-08-16 16:53:57      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:

问题介绍

有一类问题是,将数组进行整体平移,例如整体向左或向右平移3个长度,类似于这类问题的解决方案很多,下面就来尝试使用Java语言给出三种解决方法,设想问题是将一个数组整体向右平移k个单位,即若平移前数组为{1,2,3,4,5,6,7},平移3个长度后数组为{5,6,7,1,2,3,4}。

朴素思想

一般,最朴素的方法是先创建一个新数组,然后按规律将数组一一赋值即可。如下代码所示:


/**
	 * 最朴素的算法,开辟另一个数字,拷贝进去就是了
	 * @param a 输入数组
	 * @param k 移动步数
	 * 时间复杂度 O(N)
	 * 空间复杂度 O(N)
	 */
	public static void rotate1(int[] a,int k) {
		int[] b = new int[a.length];
		for(int i=0;i<k;i++) {
			b[i]=a[a.length-k+i];
		}
		for(int j=0;j<a.length-k;j++) {
			b[j+k]=a[j];
		}
		System.arraycopy(b, 0, a, 0, a.length);
	}

这种方法的时间复杂度为O(N),空间复杂度也为O(N),也是我们最常想到的方法。


冒泡思想

回想起我之前学习的冒泡排序算法的思想,感觉这问题有点像,例如5,6,7依次向上冒泡,1,2,3,4依次沉到底部,因此,我们可以借助冒泡排序的思想来解决这个问题。如下代码所示:


/**
	 * 想到冒泡排序算法的思想
	 * @param a 输入数组
	 * @param k 移动步数
	 * 时间复杂度 O(N*k)
	 * 空间复杂度 O(1)
	 */
	public static void rotate2(int[] a,int k) {
		for(int i=0;i<k;i++) {
			for(int j=a.length-k+i;j>i;j--) {
				int tmp=a[j];
				a[j]=a[j-1];
				a[j-1]=tmp;
			}
		}
	}



这种方法的时间复杂度为O(N*k),空间复杂度为O(1),借助了冒泡排序的思想。


旋转思想

仔细研究变化前后的数组我们会发现,首先将数组分解成两部分,然后分别对两部分进行旋转颠倒,最后合并成大数组再旋转一次,即可完成。如下代码所示:


/**
	 * 
	 * @param a 输入数组
	 * @param k 移动步数
	 * 时间复杂度 O(N)
	 * 空间复杂度 O(1)
	 */
	public static void rotate3(int[] a,int k) {
		reverse(a,0,a.length-k-1);
		reverse(a,a.length-k,a.length-1);
		reverse(a,0,a.length-1);
	}
	
	public static void reverse(int[]a,int start,int end) {
		for(int i=0;i<(end-start+1)/2;i++) {
			int tmp=a[start+i];
			a[start+i]=a[end-i];
			a[end-i]=tmp;
		}
	}



这种方法的时间复杂度为O(N),空间复杂度为O(1),借助了旋转的思想,比较巧妙。


数组元素整体移动问题的研究

标签:

原文地址:http://my.oschina.net/zzw922cn/blog/493154

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!