数组[n-1], 循环位移k位, 时间复杂度O(n)
方法A, 此算法的设计思路是什么呢?
1) 分为0 ~ k, k ~ n-1 两部分, 分别逆序
2) 0 ~ n-1 逆序
public class ArrayShift {
static public void shift(Object[] ary, int k) {
int n = ary.length;
k = k % n;
if(k < 0)
k = k + n;
reverse(ary, 0, n - k - 1);
reverse(ary, n - k, n - 1);
reverse(ary, 0, n - 1);
}
static void reverse(Object[] ary, int start, int end) {
Object t;
for (; start < end; start++, end--) {
t = ary[start];
ary[start] = ary[end];
ary[end] = t;
}
}
}
方法B, 自己胡乱想的,是否符合时间复杂度要求?
1) 假设右移k位, 则将数组A 最末的k个元素与 0 ~ k 交换,使得0 ~ k位置顺序符合要求, 并得到 A[k+1] , A[k+2] ..... A[1], A[2] ... A[k] 组成的长度为n-k的数组A‘
2) 如果A‘长度小于k, k = k % A.length;
3) A’ 位移k位, 递归至数组长度0 或 k = 0
public class ArrayShift {
public static void shift(Object[] ary, int k){
int n = ary.length;
k = k % n;
if (k > 0){
shiftRight(ary, 0 , n , k);
}else{
shiftRight(ary, 0 , n , n+k);
}
}
static void shiftRight(Object[] ary, int start, int n, int k){
if (n > 0 && k > 0) {
for (int i = 0; i < k; i++) {
swap(ary, n + start - k + i, start + i);
}
if ( n > k * 2 ){
shiftRight(ary, start + k, n - k, k);
}else{
int r = k % (n - k);
shiftRight(ary, start + k, n - k , r);
}
}
}
static void swap(Object[] ary, int m, int n){
Object tmp;
tmp = ary[m];
ary[m] = ary[n];
ary[n] = tmp;
}
}