字符串在单遍中通过单词反转

时间:2013-12-18 01:55:50

标签: string algorithm

是否有任何算法/技术可以在单次通过中完成字符串反转,时间复杂度为O(n),空间复杂度为O(1)。

3 个答案:

答案 0 :(得分:2)

不,除非你已经知道每个单词被允许使用某种缓冲区多长时间,否则这在一次通过中是不可能的。

试一试:

HELLO SAM
 ^
becomes
SAM HELLO
     ^

如果您只知道E(因为这是您的第一个/唯一的通行证,并且您不允许存储任何数据),您可能无法知道它需要交换到哪里目前的空间角色。到达空间并找出E所属的位置后,再次检索E为时已晚。

答案 1 :(得分:1)

如果我们可以按相反的顺序获取字符,并且每个字在内存中只需要O(1)个机器字,那么在单个遍中反转字,O(n)-time,O(1)-space算法可以使用(伪代码):

def reverse_words(text):
    word = [] # assume a word requires O(1) machine words
    for character in reversed(text): # single pass (in reverse)
        if character == ' ':
           if word: # print non-empty word
              print(''.join(reversed(word)), end=character)
              word = []
        else:
            word.append(character) # O(1)-time
    if word: # print the first word (in original text) if it is not empty
       print(''.join(reversed(word)))

示例:

>>> reverse_words("this is a string")
string a is this

注意:每个角色都会被触摸两次:第一个 - 追加,第二个 - 打印它。要理解为什么它仍然是一次通过算法,想象而不是text我们被赋予poplast()函数来弹出(获取和删除)字符序列中的最后一个字符。如果它为空序列返回None,那么循环将如下所示:

for character in iter(poplast, None): # call `poplast()` until it returns `None`
    # the rest is the same as in the first loop ..

在这种情况下,我们不能对输入进行多次传递。它在第一次通过时被销毁。

  

是否可以更改原始文本?

是。再次 if 我们可以假设最长的字长是常数(独立于n),即n增长;最大字长保持不变。

从一端一次只读一个字到两个临时缓冲区。并且由于不同端的不均匀字大小而交换它们,同时跟踪未使用的端点。交换后只有一个临时缓冲区不为空(具有不完整单词的缓冲区)。填充缓冲区,直到两端遇到完整的单词或达到中心。然后重复交换。

我想不出一个优雅的实现。如果我们对输入进行随机访问,我就不会看到一次通过要求。对于不适合内存的非常大的文件,请查看tac utility or tail -r (BSD) 如何实现(在这种情况下,一行代替单个字)。

答案 2 :(得分:1)

如果考虑一个单词可以有最大字符数为20,我们可以实现O(1)空间,O(n)时间和单次通过:)

    public static void main(String[] args) {

        reverse("Hello World HaHa");
    }

    public static void reverse(String line) {
        char[] stack = new char[20];
        int index = 0;
        for (int i = line.length() - 1; i >= 0; i--) {
            if (line.charAt(i) != ' ') {
                stack[index++] = line.charAt(i);
            } else {
                while (--index >= 0) {
                    System.out.print(stack[index]);
                }
                System.out.print(' ');
                index = 0;
            }
        }
        if (index > 0) {
            while (--index >= 0) {
                System.out.print(stack[index]);
            }
        }
    }

注意:实际时间复杂度为2n,n是字符串的长度,但是单遍!