【线性表】一维数组循环左移

2010年考研408试题

设将 n ( n > 1 ) n(n>1) n(n>1)个整数存放到一维数组 R R R中。试设计一个在时间和空间两方面都尽可能高效的算法,将 R R R中保存的序列循环左移 P ( 0 < P < n ) P(0<P<n) P(0<P<n)个位置,即将 R R R中数据由 ( X 0 , X 1 , ⋯   , X n − 1 ) (X_0,X_1,\cdots , X_{n-1}) (X0,X1,,Xn1)变换为 ( X P , X P + 1 , ⋯   , X n − 1 , X 0 , X 1 , ⋯   , X P − 1 ) (X_P, X_{P+1}, \cdots , X_{n-1}, X_0, X_1, \cdots , X_{P-1}) (XP,XP+1,,Xn1,X0,X1,,XP1)


法一
这道题最直观的想法是新设一个长度为 P P P的数组 A A A,将前 P P P个元素存入 A A A中,再将后 n − P n-P nP个元素向前移动,最后将 A A A中元素补回 R R R的最后。该算法的时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( p ) O(p) O(p)

法二
为了减小空间复杂度,可采用如下方法。
不妨设前 P P P个元素组成的序列为 A A A,后面的序列为 B B B,则 R = A B R=AB R=AB,而我们要计算的是 R ′ = B A R' = BA R=BA。现将 R R R逆置得到 R − 1 R^{-1} R1,容易发现 R − 1 = B − 1 A − 1 R^{-1} = B^{-1} A^{-1} R1=B1A1,只需再分别逆置 B − 1 B^{-1} B1 A − 1 A^{-1} A1,就可以得到最终想要的结果 R ′ = B A R' = BA R=BA

对于逆置数组,可以通过如下代码实现:

void
reverseArray(int len, int *array) {
    int start = 0, end = len - 1, temp;
    while (start <= end) {
        temp = *(array + start);
        *(array + start) = *(array + end);
        *(array + end) = temp;
        start++; end--;
    }
}

根据上面的推导,只需要三次逆置操作就可以完成:

void
answer(int n, int p, int *array) {
    reverseArray(n, array);
    reverseArray(n - p, array);
    reverseArray(p, array + n - p);
}

该方法的时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)

你可能感兴趣的:(数据结构)