In-place interleaving of the two halves of a string

后端 未结 6 1352
长发绾君心
长发绾君心 2021-02-20 07:30

Given a string of even size, say:

abcdef123456

How would I interleave the two halves, such that the same string would become

6条回答
  •  无人及你
    2021-02-20 08:04

    You may be able to do it in O(N*log(N)) time:

    Want: abcdefgh12345678 -> a1b2c3d4e5f6g7h8
    
    a b c d e f g h
      1 2 3 4 5 6 7 8
    
      4 1-sized swaps:
    
    a 1 c 3 e 5 g 7
      b 2 d 4 f 6 h 8
    
    a1  c3  e5  g7
        b2  d4  f6  h8
    
      2 2-sized swaps:
    
    a1  b2  e5  f6
        c3  d4  g7  h8
    
    a1b2  e5f6
          c3d4  g7h8
    
      1 4-sized swap:
    
    a1b2  c3d4
          e5f6  g7h8
    
    a1b2c3d4
            e5f6g7h8
    

    Implementation in C:

    #include 
    #include 
    
    void swap(void* pa, void* pb, size_t sz)
    {
      char *p1 = pa, *p2 = pb;
      while (sz--)
      {
        char tmp = *p1;
        *p1++ = *p2;
        *p2++ = tmp;
      }
    }
    
    void interleave(char* s, size_t len)
    {
      size_t start, step, i, j;
    
      if (len <= 2)
        return;
    
      if (len & (len - 1))
        return; // only power of 2 lengths are supported
    
      for (start = 1, step = 2;
           step < len;
           start *= 2, step *= 2)
      {
        for (i = start, j = len / 2;
             i < len / 2;
             i += step, j += step)
        {
          swap(s + i,
               s + j,
               step / 2);
        }
      }
    }
    
    char testData[][64 + 1] =
    {
      { "Aa" },
      { "ABab" },
      { "ABCDabcd" },
      { "ABCDEFGHabcdefgh" },
      { "ABCDEFGHIJKLMNOPabcdefghijklmnop" },
      { "ABCDEFGHIJKLMNOPQRSTUVWXYZ0<({[/abcdefghijklmnopqrstuvwxyz1>)}]\\" },
    };
    
    int main(void)
    {
      unsigned i;
    
      for (i = 0; i < sizeof(testData) / sizeof(testData[0]); i++)
      {
        printf("%s -> ", testData[i]);
        interleave(testData[i], strlen(testData[i]));
        printf("%s\n", testData[i]);
      }
    
      return 0;
    }
    

    Output (ideone):

    Aa -> Aa
    ABab -> AaBb
    ABCDabcd -> AaBbCcDd
    ABCDEFGHabcdefgh -> AaBbCcDdEeFfGgHh
    ABCDEFGHIJKLMNOPabcdefghijklmnop -> AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPp
    ABCDEFGHIJKLMNOPQRSTUVWXYZ0<({[/abcdefghijklmnopqrstuvwxyz1>)}]\ -> AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz01<>(){}[]/\
    

提交回复
热议问题