Reordering of array elements

前端 未结 4 409
予麋鹿
予麋鹿 2020-12-02 19:24

Given an array

[a1 a2 a3 ... an b1 b2 b3 ... bn c1 c2 c3 ...cn]

without using extra memory how do you reorder into an array



        
4条回答
  •  死守一世寂寞
    2020-12-02 20:20

    Assuming you mean O(1) memory (or depending on the model O(log n)) rather than no extra memory, a linear time in-place algorithm exists.

    This paper: http://arxiv.org/abs/0805.1598 has an algorithm for the case when you have

    a1 ... an b1 ... bn and want to convert to

    b1 a1 b2 a2 ... bn an.

    The paper also mentions that you can generalize this to other k-way shuffles. In your case, k = 3.

    The algorithm in the paper will give the following:

    Start with a1 a2 ... an b1 b2 ... bn c1 c2 ... cn and convert to

    c1 b1 a1 c2 b2 a2 ... cn bn an

    Another pass through this, and you can easily get a1 b1 c2 a2 b2 c2 ... an bn cn.

    Now to generalize the algorithm in the paper, we need to pick a prime p, such that k is a primitive root of p^2.

    For k = 3, p = 5 will do.

    Now to apply the algorithm, first you need to find the largest m < n such 3m+1 is a power of 5.

    Note: this will only happen when 3m+1 is an even power of 5. Thus you can actually work with powers of 25 when trying to find the m. (5^odd - 1 is not divisible by 3).

    Once you find m,

    You shuffle the array to be

    [a1 a2 ... am b1 b2 ... bm c1 c2 ... cm] [a(m+1) ... an b(m+1) ... bn c(m+1) ... cn]

    and then use the follow the cycle method(refer the paper) for the first 3m elements, using the powers of 5 (including 1 = 5^0) as the starting points of the different cycles) and do a tail recursion for the rest.

    Now to convert a1 a2 ... an b1 b2 ... bn c1 c2 ... cn

    to

    [a1 a2 ... am b1 b2 ... bm c1 c2 ... cm] [a(m+1) ... an b(m+1) ... bn c(m+1) ... cn]

    you first do a cyclic shift to get

    a1 a2 ... am [b1 b2 bm a(m+1) .. an] b(m+1) .. bn c1 c2 ... cn

    (the elements in the square brackets are the ones that were shifted)

    Then do a cyclic shift to get

    a1 a2 ... am b1 b2 bm a(m+1) .. an [c1 c2 ..cm b(m+1) .. bn ] c(m+1) ... cn

    And then a final shift to

    a1 a2 ... am b1 b2 bm [c1 c2 ..cm a(m+1) .. an ] b(m+1) .. bn c(m+1) ... cn

    Note that cyclic shift can be done in O(n) time and O(1) space.

    So whole algorithm is O(n) time and O(1) space.

提交回复
热议问题