数组循环移位

转载于:编程之美

问题:设计一个算法,把一个含有n个元素的数组A循环右移k位,要求时间复杂度是O(n)的。举个例子说明一下算法要达到的效果:数组中包含的元素为123456,现在要循环右移2位,则变成了561234 。


分析:对于这个问题,1:我们最常规的算法就是一步一步移位,直到移动K次,但是这样的算法复杂度是O(k*N);然后我们优化一下;既然是循环移位,那么就有个循环周期,这个循环周期就是数组大小,例如对于一个8位的数组,你移动14次跟你移动14%8=6次是一样的,所以我们可以将k进行简化k=k%N,然后再使用上面一步一步移位的算法;这样的化算法复杂度是O((k%N)*N)还是达不到我们的要求,怎么办那就要仔细分析一下移位规律了。考虑一下数组A中元素123456循环右移2位到底是怎么个情况!!!可不可以这样实现呢?将数组A分成两个部分:A[0~n-k-1] 和 A[n-k~n-1] ,将这两个部分分别翻转,然后放在一起在翻转(逆序)。具体是这样的:

(1)翻转1234:123456 ---> 432156

(2)翻转56:     432156 ---> 432165

(3)翻转432165:432165 ---> 561234

看看吧,确实完成了翻转的操作。

代码如下:

两种解法:第一个k%N简化,第二个反转

public class Array_shift 
{
	public static void main(String[] args) //循环移位直接是在原数组里面进行的所以会破坏原数组。
	{
		int a[]={1,2,3,4,5,6,7,8};
		int b[]={1,2,3,4,5,6,7,8};
		shieft_1(a,5);
		shieft_2(b,5);
		print(a);
		print(b);
	}
	public static void shieft_1(int[] a,int k) //第一种解法 简化k=k%N。
	{
		int length = a.length;
		k=k%(length);
		while(k!=0)
		{
			int t = a[length-1];
			for(int i=length-1;i>0;i--)
			{
				a[i]=a[i-1];
			}
			a[0]=t;
			k--;
		}
	}
	public static void shieft_2(int[] a,int k)  //第二种解法,利用翻转进行操作
	{
		int length = a.length;
		k=k%length;
		reverse(a,0,length-k-1);
		reverse(a,length-k,length-1);
		reverse(a,0,length-1);
	}
	public static void reverse(int[] a,int start,int end)
	{
		for(int i=start;i<end;i++,end--)
		{
			int temp=a[end];
			a[end]=a[i];
			a[i]=temp;
		}
	}
	public static void print(int[] a)
	{
		for(int i=0;i<a.length;i++)
		{
			System.out.print(a[i]+" ");
		}
		System.out.println();
	}
}
运行结果如下:

4 5 6 7 8 1 2 3 
4 5 6 7 8 1 2 3 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值