简体   繁体   中英

Find All Palindrome Substrings in a String by Rearranging Characters

For fun and practice, I have tried to solve the following problem (using C++): Given a string, return all the palindromes that can be obtained by rearranging its characters.

I've come up with an algorithm that doesn't work completely. Sometimes, it finds all the palindromes, but other times it finds some but not all.

It works by swapping each adjacent pair of characters N times, where N is the length of the input string. Here is the code:

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

What's the fault in this algorithm? I'm mostly concerned about the functionality of the algorithm, rather than the efficiency. Although I'll appreciate tips about efficiency as well. Thanks.

This probably fits a bit better in Code Review but here goes:

Logic Error

You change charactersSet while iterating over it, meaning that your iterator breaks. You need to make a copy of characterSet , and iterate over that.

Things to Change

Since pals holds only unique values, it should be a std::set instead of a std::vector . This will simplify some things. Also, your isPalandrome method spells palindrome wrong!

Alternative Approach

Since palindromes can only take a certain form, consider sorting the input string first, so that you can have a list of characters with an even number of occurrences, and a list of characters with an odd number. You can only have one character with an odd number of occurrences (and this only works for an odd length input). This should let you discard a bunch of possibilities. Then you can work through the different possible combinations of one half of the palindrome (since you can build one half from the other).

Here is another implementation that leverages 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;
}

We first sort the original string. This is required for std::next_permutation to work correctly. A call to the isPalindrome function with a permutation of the string is done in a loop. Then if the string is a palindrome, it's stored in the set. The subsequent call to std::next_permutation just rearranges the string.

Here is a Live Example . Granted, it uses a reversed copy of the string as the "isPalindrome" function (probably not efficient), but you should get the idea.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM