最小化 map<string, string> 的双端队列中连续相等提取的数量
Posted
技术标签:
【中文标题】最小化 map<string, string> 的双端队列中连续相等提取的数量【英文标题】:Minimize the number of consecutive equal extractions in a deque of map<string, string> 【发布时间】:2011-12-02 11:20:19 【问题描述】:我希望这个地方最适合这类问题。
我有以下问题(我认为比看起来更复杂)。
我正在使用字符串的双端队列(deque)数据结构。 deque 提取;
deque只包含N个不同的字符串,每个字符串以随机顺序重复M次,所以deque的长度为N*M,例如假设M=4, N=2, string1="A" , string2="B":
extractions[1] = "A"
extractions[2] = "A"
extractions[3] = "B"
extractions[4] = "B"
extractions[5] = "A"
extractions[6] = "B"
extractions[7] = "B"
extractions[8] = "A"
我正在寻找一种算法,它可以让我找到一个有趣的配置,其中没有两个连续相等的元素,在这种情况下应该只有两个解决方案,“A”,“B”, A","B","A","B","A","B" 和 "B","A","B","A","B","A","B “,“一种”。 对于“有趣”的配置,我的意思不是简单地由 N 个嵌套循环给出的配置。
我实施的一个非常愚蠢的解决方案是用std::random_shuffle
随机洗牌,直到找不到连续相等的元素,但这既愚蠢又缓慢,这更像是一个 bogosort...
显然最大化字符串之间的编辑距离应该更好。 有什么提示吗?
【问题讨论】:
很容易生成没有连续相同元素的配置。您是否正在寻找一个特定的配置(例如,最接近您的初始配置的配置,或者类似的配置)? 不,我对特定配置不感兴趣,唯一的问题是应该避免连续提取。显然这个例子很糟糕,但是对于 N=3,我们可以有更多有趣的例子,N=3 M=3 的可能允许配置应该是 A,B,C,B,A,C,A,B,C 而不仅仅是简单的配置:A,B,C,A,B,C,A,B,C 这种配置基本上都是我开始的,所以没什么意思。 那么你需要澄清你的问题,说明你正在寻找“有趣”的配置,并定义“有趣”的确切含义。 您提出的解决方案与bogosort 非常相似。 【参考方案1】:从一个简单的配置开始,例如 N=4 和 M=4,从
A B C D A B C D A B C D A B C D
然后运行一个标准的洗牌算法,但要遵守不要让两个相等的元素彼此相邻的约束,即
for i = 0 .. N*M - 2
let j = random(N*M - 2 - i) + i + 1
if ((i == 0 || array[i - 1] != array[j])
&& (array[i + 1] != array[j])
&& (array[i] != array[j - 1])
&& (j == N*M - 1 || array[i] != array[j + 1]))
swap (array[i], array[j])
这应该会很快为您提供一个随机配置,以满足您不具有两个连续相等元素的要求。
【讨论】:
random(n) 函数应该返回什么? [0,n) 范围内的随机数?或在 [1,n] 范围内? 是的,这绝对有效,但必须应用到没有连续的。我会用一段时间( sumConsecutiveElements(array) != 0 ) yourFunction(array) 将它括起来,其中 sumConsecutiveElements(array) 是一个返回连续相等元素数量的函数。感谢您的精彩回答! 直到没有连续时才需要应用,因为算法确保在算法执行过程中的任何时刻都没有......【参考方案2】:int total = m * n;
for (int i = 1; i < total - 1; i++)
int j = total - 1;
while ((j > i) && (queue[i - 1] == queue[j]))
j--;
if (queue[i - 1] == queue[j])
String aux = queue[i - 1];
queue[i - 1] = queue[j];
queue[j] = aux;
此代码未经测试,但您明白了。
【讨论】:
在第一次实现时,此解决方案不起作用,然后辅助字符串无用,一个简单的 std::swap 可以为您完成这项工作。也许这是我的实现错误,但我用 .at() 和迭代器测试了它......【参考方案3】:我会用递归来做:
示例在 C# 中:我发现它比嵌套循环更“会说话”:
public List<String> GetPermutations(string s, IEnumerable<String> parts, string lastPart, int targetLength)
List<String> possibilities = new List<string>();
if (s.Length >= targetLength)
possibilities.Add(s);
return possibilities;
foreach (String part in parts)
if (!part.Equals(lastPart))
possibilities.AddRange(
GetPermutations(s + part, parts, part, targetLength));
return possibilities;
用法:
List<String> parts = new List<String>() "A", "B", "C";
int numOccurences = 4;
List<String> results =
GetPermutations("", parts, "", numOccurences * parts.Count );
但如果您只想要一个可能的解决方案(当然计算速度更快):
它将为您创建一个随机的、非平凡的解决方案,例如:CACBCBCABABACAB(用于 A、B、C)
public String GetRandomValidPermutation(
string s,
List<String> parts,
string lastPart,
int targetLength)
if (s.Length >= targetLength)
return s;
String next = String.Empty;
while(
(next = parts[new Random().Next(0, parts.Count)])
.Equals(lastPart)
)
return GetRandomValidPermutation(s + next, parts, next, targetLength);
呼叫:
String validString =
GetRandomValidPermutation("", parts, "", numOccurences * parts.Count);
【讨论】:
是的,但这并不能帮助我解散列表,只会产生一个简单的配置 A,B,C,A,B,C,A,B,C...我错了吗? 它返回有效组合的完整列表。从 ABA 开始...以 ZYZ 结尾...(如果是整个字母表)。以上是关于最小化 map<string, string> 的双端队列中连续相等提取的数量的主要内容,如果未能解决你的问题,请参考以下文章