没有连续重复的字典顺序

Lexicographic ordering with no consecutive repetition

我知道字典顺序算法,但是在这个问题中我们可以重复字符非consecutively.And这让我很困惑。

一个好的字符串 s 是:

  1. 仅包含集合中的这些字母:[a,b,c]
  2. s[i] != s[i+1] 字符串 aba、bca、cbc 有效,但 aaa、abb、aab 无效。

集合顺序:[a, b, c]

["aba", "abc", "aca", "acb", "bab", "bac", "bca", "bcb", "cab", "cac", "cba", "cbc"].

你能帮我看看它的算法吗

听起来你想做的是使用字典顺序进行排序,然后过滤掉你认为无效的结果。

在您的示例中,第 1 步将是:

["aaa", "aab", "aac", ...]

然后删除无效的,你会得到:

["aba", "abc", "aca", ...]

您可以按字典顺序对字符串列表进行排序。这些将包含具有相同连续字符的字符串。因此,在 return 结果之前,您可以制作另一个列表并循环遍历原始列表,同时只将符合上述条件的字符串包含到新列表中。一旦你遍历了整个列表,就 return 它就是你的最终答案。

例如。考虑一个列表 -

 ["cab", "abc", "aca", "acc", "abb", "bbc", "caa", "aab"]

排序后-

['aab', 'abb', 'abc', 'aca', 'acc', 'bbc', 'caa', 'cab']

现在您可以遍历此列表并只选择符合您条件的元素。所以最终列表将是 -

['abc', 'aca', 'cab']

希望您理解该方法。

您可以使用递归算法,将上次使用的字母作为下一次选择的禁止字母传递。递归函数获取一个大小参数,因此它知道应该生成的字符串应该有多长。然后它迭代每个可能的字符,但排除禁止的字符,并递归调用函数,但大小减小。当前字符现在成为递归调用的禁止字符。当该调用返回结果时,它会在每个结果前加上当前字符作为前缀,以便有效地将它们的大小都增加一个字符。对于迭代的所有其他字符(禁止的字符除外)重复此操作。并将所有这些结果收集到一个结果集(数组)中,并返回。

我假设字符集是按字典顺序提供的(否则在使用下面的算法之前对其进行排序),并且生成的字符串的大小也是给算法的参数。

这是该想法的一个简单 JavaScript 实现:

function combis(chars, size, forbidden="") {
    if (size == 0) { // base case
        return [""];
    }
    let results = [];
    for (let chr of chars) {
        if (chr != forbidden) { // Avoid repetition
            for (let combi of combis(chars, size-1, chr)) {
                results.push(chr + combi); // prefix the returned string
            }
        }
    }
    return results;
}

console.log(combis("abc", 3));