java - 字符串的两半就地交错

标签 java c++ c algorithm math

给定一个偶数大小的字符串,说:

abcdef123456

我如何交错两半,这样相同的字符串会变成这样:

a1b2c3d4e5f6

我曾尝试开发一种算法,但未能成功。有人能给我一些关于如何进行的提示吗?我需要在不创建额外的字符串变量或数组的情况下执行此操作。一两个变量就可以了。

我只是不想要一个工作代码(或算法),我需要开发一个算法并用数学证明它的正确性。

最佳答案

你可以在 O(N*log(N)) 时间内完成:

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

C 中的实现:

#include <stdio.h>
#include <string.h>

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;
}

输出(ideone):

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

关于java - 字符串的两半就地交错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15996288/

相关文章:

在 Unix 系统上创建子进程?

java - 如何在java中解码base64

java - 表情符号字符序列👇打破了旧的 XML 过程

c++ - 字符串数组输出

c++ - 在 C++ 中读取最后一行

c++ - 如何在同一行输入 3 个整数并将其存储为 3 个不同的变量?

c - execvp - 为什么我的程序退出?

java - iText:成功调整一页pdf,但当pdf文档中有多个页面时失败

java - 在Android中什么时候应该使用锁,什么时候应该使用synchronized?有区别吗?

c - atoi 的等效功能不起作用