反转字符数组中单词的顺序

Posted

技术标签:

【中文标题】反转字符数组中单词的顺序【英文标题】:Reversing the order of words in a character array 【发布时间】:2013-07-11 13:39:00 【问题描述】:

问题是特殊字符的位置(例如:'?'、','、''、'.')应该保持不变。所以对于输入字符串“Hello World,你好吗?”输出将是“你是,你好吗?世界你好?”。现在对于没有特殊字符的字符串,O(n) 算法是将每个单词反转然后反转整个数组,但这并没有考虑特殊字符。

我想出的最佳算法如下。我们遍历数组并将每个单词压入堆栈顶部,然后将特殊字符排入队列。然后,我们同时从堆栈和队列中弹出元素,并将它们组合起来形成所需的输出。

是否有就地 O(n) 算法?如果没有,您能否建议一个没有额外空间的 O(n^2) 算法。还假设,您不能使用任何字符串库函数。

【问题讨论】:

reverse a string word by word的可能重复 请查看:***.com/questions/12879348/… 正在使用 std::string (仅用于字符串表示)和 std::istream 好吗? 你的算法是 O(n) OP 正在寻找合适的算法。 【参考方案1】:

所以,这是一个想法。

1) 初始字符串

"Hello World, how are you?"

2) 反转字符串,但不包含任何最后的特殊字符

"uoy era woh ,dlroW olleH?"

3) 反转字符串中的单词

"you are how ,World Hello?"

4) 为字符串的开头和结尾创建一个迭代器(指针、索引,无论您使用什么),递增/递减每个迭代器,直到它们碰到非单词。非单词是指空格或特殊字符。所以在这种情况下,递增的迭代器首先会遇到“you”和“are”之间的空白,而递减的迭代器会遇到“world”和“Hello”之间的空白,如下所示。

"you are how ,World Hello?"
    ^              ^

5) 如果没有特殊字符,则继续,但如果您遇到特殊字符。反转迭代器之间的所有内容,包括它们指向的字符。下面显示了这种情况发生的时间

"you are how ,World Hello?"
        ^    ^

6) 现在我们看到了反转的结果。

"you are, woh World Hello?"

根据 johnchen902 的评论进行编辑

7) 现在在这些迭代器之间反转子字符串,不包括在步骤 (5) 中找到的特殊字符。

"you are, how World Hello?"

8) 返回步骤 (5)。

我还没有编写代码,解释起来有点棘手,但我希望你能理解

【讨论】:

不适用于A,B,C D E。建议的修复:(7) 反转迭代器之间的 子字符串,不包括 (5) 中找到的特殊字符。 (8) 转到 (5) 很好,johnchen902,我认为现在应该可以了。我想我原来的解决方案只适用于奇数个特殊字符。我将编辑我的帖子以包含您的建议 你能检查测试用例“Hello World,你好吗?”在我看来,该算法可能不起作用。 (请注意逗号前后都有一个空格)考虑多个特殊字符同时出现的测试用例。 您好,用户。所以我没有对此进行编码,但我确实把它草草写了下来,然后我得到了“你是,你好,世界怎么样?” 'How' 和 'World' 之间有 2 个空格,尽管我想你希望得到“You Are , How World Hello?”你是吗?如果不是,也许需要更明确的规则。您可以修改步骤 4-5,以便迭代器在到达后面没有字母的空格时停止。当你坐下来开始考虑这些案件时,这是一个有点棘手的小难题,但我认为基础在这里。 为什么字符串 " are how, World " 没有反转?这是算法遇到特殊字符的第一个实例。一旦我清除了所有的疑虑,我会试运行算法并很快开始真正编码。【参考方案2】:

对于就地算法,只需创建两个迭代器(对单词进行迭代),一个反向迭代器,另一个向前迭代。

您的循环将仅包含以下内容:

while(FirstIteratorIsBefore(forward_iterator, backward_iterator)) 
  if(IsSpecialCharacter(*forward_iterator)) 
    ++forward_iterator;
   else if(IsSpecialCharacter(*backward_iterator)) 
    ++backward_iterator;
   else 
    // Swap the two
    Swap(forward_iterator, backward_iterator);
    ++forward_iterator;
    ++backward_iterator;
  

注意:您必须创建自己的简单单词迭代器才能使此逻辑正常工作,但这很容易实现。

【讨论】:

您无法比较不同类别的迭代器(至少不符合标准的迭代器)。 感谢@jrok,我已经更新了代码以反映这一点。请注意,由于这些是您自己的迭代器,您的 FirstIteratorIsBefore 只是检查它正在迭代的原始字符串中的位置。 鉴于这是给出解决方案的唯一答案,否决投票者能否解释一下? 抱歉,我无法按照您的代码进行操作。可以给我解释一下吗? @user2560730 我现在正要离开,但请阅读有关矢量和地图之类的 stl 迭代器的信息。此解决方案使用迭代器的概念。您需要在 Swap() 中做一些工作,以便能够处理不同大小的单词,其中文本必须移动到位并且迭代器内的内部位置也需要更改。

以上是关于反转字符数组中单词的顺序的主要内容,如果未能解决你的问题,请参考以下文章

反转字符串

JSFL 命令将文本字段拆分为单词 - Flash 数组顺序错误

反转字符串中单词顺序的程序错误地打印反转的字符串

反转单词顺序 VS 左旋转字符串

ACM之反转字符串里的单词

如何在 C++ 中反转字符数组? [关闭]