【问题标题】:Generate all possible combinations that are palindrome from a given string (Javascript)从给定的字符串(Javascript)生成所有可能的回文组合
【发布时间】:2017-08-07 01:22:27
【问题描述】:

我有一个字符串“racecarzz”,我想从该字符串中生成每个字符的所有可能组合,这些组合可以以相同的方式前后读取(回文)。

检查回文并不难string.split('').reverse().join(''),但生成可能的组合对我来说非常具有挑战性。

输入:

str = 'racecarzz'

输出:

arr = ['rar', 'cec', 'raar', 'caac', 'craarc', 'racecar', 'raczezcar', 'zracecarz', ...]`

我已经尝试了 get-all-combinations-for-a-string 的解决方案,但它仍然缺少一些像“zracecarz”、“raczezcar”等...

    var combinations = function (string) {
    var result = [];
    var loop = function (start,depth,prefix) {
        for (var i=start; i<string.length; i++) {
            var next = prefix+string[i];
            if (depth > 0) {
                loop(i+1,depth-1,next);
            } else {
                //check for Palindrome
                if (next == next.split('').reverse().join('')) {
                    result.push(next);
                }
            }
        }
    }
    for (var i=0; i<string.length; i++) {
        loop(0,i,'');
    }
    //remove duplicate
    result = result.filter(function(val, ind){
      return result.indexOf(val)==ind;
    });
    return result;
}
document.querySelector('#demo').innerHTML = combinations('racecarzz').join('<br>');
&lt;div id="demo"&gt;&lt;/div&gt;

以上回报:

["r", "a", "c", "e", "c", "a", "r", "z", "z", "rr", "aa", "cc", "zz", "rar", "rcr", "rer", "rcr", "rar", "aca", "aea", "aca", "cec", "raar", "rccr", "acca", "racar", "raear", "racar", "rcecr", "aceca", "raccar", "racecar"]

参考:https://jsfiddle.net/f77g15tx/1/

【问题讨论】:

  • “但生成可能的组合对我来说非常具有挑战性。” 您在代码和/或算法过程的哪个部分遇到问题?您能否包括您尝试解决查询的代码和/或算法?
  • @RobbyCornelissen 链接问题中提到的“回文”在哪里?
  • 你可以找到所有的排列,并一一检查回文
  • @guest271314 OP 声明:检查回文并不困难 [...] 但生成可能的组合对我来说非常具有挑战性。
  • @guest271314 显然你和土豆皮一起投票支持复制品;当 SO 这样做时,这很令人困惑。我的评论是针对他的。

标签: javascript string algorithm permutation palindrome


【解决方案1】:

如果您只想生成回文(不必先生成所有字符的所有可能组合,然后过滤掉非回文),请将输入中的字符分成两组,具体取决于它们出现的频率:

input:   racecarzz
singles: e
doubles: carz

然后,用双打中的字符生成每个组合:

c, a, r, z, ca, cr, cz, ac, ar, az ... zrca, zrac  

然后,使用这些组合中的每一个,创建 3 个回文:一个不重复最后一个字符,一个重复最后一个字符,一个在中间有单个字符:

c    -> c, cc, cec
ca   -> cac, caac, caeac
car  -> carac, carrac, carerac
carz -> carzrac, carzzrac, carzezrac
...

如果有多个单曲,请用这些单曲中的每一个创建回文:

car -> carac, carrac, carerac, carfrac, cargrac ...  

不要忘记自己添加单个字符; “e”也是回文。

如果一个字符出现 3 次,则将其添加一次到双打,一次添加到单打。如果它出现 4 次,则将其添加到双打中,依此类推...(这将创建重复的输出;如果您只想要唯一的解决方案,则必须在生成组合时避免重复,并检查最后一个字符在生成回文的同时与单打组合。)


这是基本版的代码示例:

function splitInput(str) {
    var singles = [], doubles = [];
    for (var i in str) {
        var char = str.charAt(i);
        var pos = singles.indexOf(char);               // check if already in singles
        if (pos == -1) singles.push(char);             // add to singles
        else doubles.push(singles.splice(pos, 1)[0]);  // move to doubles
    }
    return {singles: singles, doubles: doubles};
}

function generateCombinations(set) {
    var combis = [];
    addChar([], set);               // start recursion with empty partial and full set
    return combis;

    function addChar(partial, set) {
        for (var i in set) {
            var setCopy = set.slice();
            var parCopy = partial.concat(setCopy.splice(i, 1)); // add char to partial
            combis.push(parCopy);
            if (setCopy.length) addChar(parCopy, setCopy);    // recurse if chars left
        }
    }
}

function generatePalindromes(combis, singles) {
    var palins = singles.slice();                      // each single is a palindrome
    for (var i in combis) {
        var pos = combis[i].length;
        var pal = combis[i].concat([' ']);             // add space for single
        pal = pal.concat(combis[i].reverse());         // add reverse
        for (var j in singles) {
            pal.splice(pos, 1, singles[j]);            // insert single in the middle
            palins.push(pal.join(''));
        }
        pal.splice(pos, 1); palins.push(pal.join('')); // remove single
        pal.splice(pos, 1); palins.push(pal.join('')); // remove repeated last char
    }
    return palins;
}

function palindromeCombinations(input) {
    var sets = splitInput(input);
    var combis = generateCombinations(sets.doubles);
    return generatePalindromes(combis, sets.singles);
}

document.write("racecarzz &rarr; " + palindromeCombinations("racecarzz"));

如果字符可以在输入中出现 3 次或更多次,并且您只想生成唯一的解决方案,请将代码调整为:

  • 生成组合时,在迭代集合时跳过重复字符。
  • 生成回文时,如果最后一个字符是单字符之一,则跳过没有重复最后一个字符的回文。

这只需更改几行:

function splitInput(str) {
    var singles = [], doubles = [];
    for (var i in str) {
        var char = str.charAt(i);
        var pos = singles.indexOf(char);               // check if already in singles
        if (pos == -1) singles.push(char);             // add to singles
        else doubles.push(singles.splice(pos, 1)[0]);  // move to doubles
    }
    return {singles: singles, doubles: doubles};
}

function generateCombinations(set) {
    var combis = [];
    addChar([], set);               // start recursion with empty partial and full set
    return combis;

    function addChar(partial, set) {
        for (var i = 0; i < set.length; i++) {              // instead of for i in set
            if (set.indexOf(set[i]) != i) continue;       // skip duplicate characters
            var setCopy = set.slice();
            var parCopy = partial.concat(setCopy.splice(i, 1)); // add char to partial
            combis.push(parCopy);
            if (setCopy.length) addChar(parCopy, setCopy);    // recurse if chars left
        }
    }
}

function generatePalindromes(combis, singles) {
    var palins = singles.slice();                      // each single is a palindrome
    for (var i in combis) {
        var pos = combis[i].length;
        var pal = combis[i].concat([' ']);             // add space for single
        pal = pal.concat(combis[i].reverse());         // add reverse
        for (var j in singles) {
            pal.splice(pos, 1, singles[j]);            // insert single in the middle
            palins.push(pal.join(''));
        }
        pal.splice(pos, 1); palins.push(pal.join('')); // remove single
        if (singles.indexOf(pal.splice(pos, 1)[0]) == -1) { // if last not in singles
            palins.push(pal.join(''));                 // without repeated last char
        }
    }
    return palins;
}

function palindromeCombinations(input) {
    var sets = splitInput(input);
    var combis = generateCombinations(sets.doubles);
    return generatePalindromes(combis, sets.singles);
}

document.write("rarerara &rarr; " + palindromeCombinations("rarerara"));

【讨论】:

  • 就像魔术一样。谢谢!我添加了以下内容以按长度对数组进行排序,然后按字母顺序返回 dataSet.sort(function(a, b){ return a.length-b.length || a.localeCompare(b); });
  • @aznmunkey 我添加了一个代码示例,该示例仅在输入包含出现 3 次或更多次的字符时生成唯一的解决方案。
猜你喜欢
  • 1970-01-01
  • 2017-11-23
  • 1970-01-01
  • 1970-01-01
  • 2018-06-29
  • 2012-02-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多