通过重新排列字符查找字符串中的所有Palindrome子字符串

时间:2016-08-10 02:58:52

标签: c++ algorithm palindrome

为了好玩和练习,我试图解决以下问题(使用C ++):Given a string, return all the palindromes that can be obtained by rearranging its characters.

我想出了一种完全不起作用的算法。有时候,它会找到所有的回文,但有时会找到一些而不是全部。

它的工作原理是交换每对相邻的字符对N次,其中N是输入字符串的长度。这是代码:

std::vector<std::string> palindromeGen(std::string charactersSet) {
    std::vector<std::string> pals;
    for (const auto &c : charactersSet) {
        for (auto i = 0, j = 1; i < charactersSet.length() - 1; ++i, ++j) {
            std::swap(charactersSet[i], charactersSet[j]);
            if (isPalandrome(charactersSet)) {
                if (std::find(pals.begin(), pals.end(), charactersSet) == pals.end()) {
                    // if palindrome is unique
                    pals.push_back(charactersSet);
                }
            }
        }
    }
    return pals;
}

此算法有什么问题?我最关心的是算法的功能,而不是效率。虽然我也很欣赏有关效率的提示。感谢。

2 个答案:

答案 0 :(得分:1)

这在Code Review中可能会更好一些,但这里有:

逻辑错误

在迭代时更改charactersSet,这意味着迭代器会中断。您需要制作characterSet的副本,并对其进行迭代。

要改变的事情

由于pals仅包含唯一值,因此它应为std::set而不是std::vector。这将简化一些事情。此外,您的isPalandrome方法使回文错误!

替代方法

由于回文只能采用某种形式,因此请考虑首先对输入字符串进行排序,这样就可以得到偶数次出现的字符列表和一个奇数字符列表。您只能有一个具有奇数出现次数的字符(这仅适用于奇数长度输入)。这应该让你放弃一堆可能性。然后你可以通过一半回文的不同组合(因为你可以从另一半构建一半)。

答案 1 :(得分:1)

这是另一个利用std::next_permutation的实现:

#include <string>
#include <algorithm>
#include <set>

std::set<std::string> palindromeGen(std::string charactersSet) 
{
    std::set<std::string> pals;
    std::sort(charactersSet.begin(), charactersSet.end());
    do
    {
        // check if the string is the same backwards as forwards
        if ( isPalindrome(charactersSet)) 
           pals.insert(charactersSet);
    } while (std::next_permutation(charactersSet.begin(), charactersSet.end()));
    return pals;
}

我们首先对原始字符串进行排序。这是std::next_permutation正常工作所必需的。使用字符串的排列调用isPalindrome函数是在循环中完成的。然后,如果字符串是回文,它就存储在集合中。随后对std::next_permutation的调用只是重新排列字符串。

这是Live Example。当然,它使用字符串的反向副本作为“isPalindrome”函数(可能效率不高),但你应该明白这一点。