【问题标题】:Compact, readable, efficient C++ algorithm to reverse the words of a string IN-PLACE [duplicate]紧凑、可读、高效的 C++ 算法来反转字符串 IN-PLACE [重复]
【发布时间】:2015-04-20 04:10:50
【问题描述】:

所以我正在尝试为提示提出一个好的 C++ 解决方案

"将字符串中的单词倒序(单词被一个或多个分隔 空格)。现在就地进行。迄今为止最流行的字符串问题!”

而我现在拥有的是一个怪物:

void reverse_words ( std::string & S )
{
/* 
    Programming interview question: "Reverse words in a string (words are separated by one or more spaces). Now do it in-place. By far the most popular string question!"
    http://maxnoy.com/interviews.html 
*/
    if (S.empty()) return;
    std::string::iterator ita = S.begin() , itb = S.end() - 1;
    while (ita != itb) 
    {
      if (*ita != ' ')
      {
         std::string sa; // string to hold the current leftmost sequence of non-whitespace characters
         std::string::iterator tempa = ita; // iterator to the beginning of sa within S
         while (ita != ' ' && ita != itb) sa.push_back(*ita++); // fill sa
         while (*itb == ' ' && itb != ita) --itb; // move itb back to the first non-whitespace character preceding it
         std::string sb; // string to hold the current rightmost sequence of non-whitespace characters
         std::string::iterator tempb = itb; // iterator to the end of sb within S
         while (*itb != ' ' && itb != ita) sb.push_back(*itb--); // fill sb
         S.replace(tempa, ita-tempa, sb); // replace the current leftmost string with the current rightmost one
         S.replace(tempb, itb-tempb, sa); // and vice-versa
       }
      else
      {
         ++ita; 
      }
    }   
}

我认为我的想法是正确的(找到第一个字符串,将其与最后一个字符串交换,找到第一个字符串之后的下一个字符串,将其与最后一个字符串之前的字符串交换,等等),但我需要一些更好的工具来做到这一点。如何利用标准库来解决这个问题?

【问题讨论】:

  • “紧凑、可读、高效”——目标艰巨。
  • 通常的做法是反转整个字符串。然后反转每个单词。
  • 就目前而言,您的算法还没有到位

标签: c++ algorithm


【解决方案1】:

如果您使用以下方法,这非常简单:

  1. 反转整个字符串。
  2. 单独反转每个单词。

这个算法已经是O(n)了,你只需遍历整个字符串一次又一次地找到每个单词的反向。

现在,为了提高效率,请查看反转序列的算法,该算法从前面和后面读取一个并将每个存储在另一个位置。现在,每当你存储一个空格时,你只是终止了一个单词,所以现在就反转这个单词。更有效的原因是包含该单词的缓存在 CPU 上仍然很热。这里的困难是在极端情况下做到这一点。您必须考虑中间词、多个连续空格和字符串两端的空格。

【讨论】:

    【解决方案2】:

    我想就是这样。简单、高效、清晰。注意std::basic_string::find...pos >= str.size() 时返回npos

    void ReverseWords(std::string& msg) {
        std::string::size_type pos_a = 0, pos_b = -1;
        while ((pos_a = msg.find_first_not_of(' ', pos_b + 1)) != msg.npos) {
            pos_b = std::min(msg.find(' ', pos_a + 1), msg.size());
            std::reverse(msg.begin() + pos_a, msg.begin() + pos_b);
        }
        std::reverse(msg.begin(), msg.end());
    }
    

    【讨论】:

      猜你喜欢
      • 2019-04-05
      • 1970-01-01
      • 2014-12-09
      • 1970-01-01
      • 1970-01-01
      • 2020-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多