一、第一种方法,都想得到的。
static int[] LeftShift1(int[] arr,int K){//K为循环左移位数
int N=arr.length;
int[] new_arr=new int[N]; //新开一个数组,空间复杂度O(n)
for(int i = 0; i <N; i++)
new_arr[i] = arr[(K+i)%N ];
return new_arr;
}
二、利用“翻转”完成优化,《编程之美》上的算法
考虑一下数组A中元素1234567循环左移2位到底是怎么个情况!!!将数组A分成两个部分:A[0~k-1] 和 A[k~n-1] ,(12与34567)将这两个部分分别翻转,然后放在一起在翻转(逆序)。具体是这样的:
(1)翻转12:12 ---> 21
(2)翻转34567: 34567 ---> 76543
(3)一起翻转2176543:2176543 --->3456712
//翻转b~e
static void Reverse(int[] arr, int b, int e){
while(b < e){
int temp = arr[e]; //只需新开一个辅助空间
arr[e] = arr[b];
arr[b] = temp;
b++;
e--;
}
}
//左移K位
static void LeftShift(int[] arr, int K){
int N=arr.length;
//如果K>N,取K=K%N。
K %= N;
Reverse(arr, 0, K - 1);
Reverse(arr, K, N - 1);
Reverse(arr, 0, N - 1);
}
第一种算法有O(n)的空间复杂度,第二种有O(1)的空间复杂度,两种算法时间复杂度同为O(n)。
测试程序:
public class Test{
//方法一
static int[] LeftShift1(int[] arr,int K){//K为循环左移位数
int N=arr.length;
int[] new_arr=new int[N];
for(int i = 0; i <N; i++)
new_arr[i] = arr[(K+i)%N ];
return new_arr;
}
static void print(int[] arr){
for(int i=0;i<arr.length;i++)
System.out.print(arr[i]+" ");
System.out.println();
}
//翻转b~e
static void Reverse(int[] arr, int b, int e){
while(b < e){
int temp = arr[e];
arr[e] = arr[b];
arr[b] = temp;
b++;
e--;
}
}
//方法二
static void LeftShift(int[] arr, int K){
int N=arr.length;
K %= N;
Reverse(arr, 0, K - 1);
Reverse(arr, K, N - 1);
Reverse(arr, 0, N - 1);
}
public static void main(String[] args){
int[] a={1,2,3,4,5,6,7};
print(a);
int[] new_arr = LeftShift1(a,2);
print(new_arr);
// Reverse(a,2,5);
LeftShift(a, 4);
print(a);
}
}
运行:
C:\ex>java Test
1 2 3 4 5 6 7
3 4 5 6 7 1 2
5 6 7 1 2 3 4