我想要一个采用以下参数的字符串改组算法:
void CRLimitedShuffle(char* Str, uint8_t MaxConsecutiveRepetition);
Run Code Online (Sandbox Code Playgroud)
该函数应对输入字符串执行随机洗牌。然而:
MaxConsecutiveRepetition,即结果字符串中最多MaxConsecutiveRepetition允许出现连续的相同字符。例如:
Str="aaaaabbbbb";
MaxConsecutiveRepetition=3;
Run Code Online (Sandbox Code Playgroud)
对于上面的参数,“aabbbaaabb”是正确的结果,而“aaabaabbbb”是不正确的,因为它有 4 个连续的“b”,超过MaxConsecutiveRepetition。
一个天真的想法是对打乱的结果进行审核,如果不符合要求就重新打乱。然而,对于某些极端情况,性能可能会极低。例如:
Str="aaaabbbbbbbbbb";
MaxConsecutiveRepetition=2;
Run Code Online (Sandbox Code Playgroud)
在这个例子中,只有“bbabbabbabbabbabb”是正确的输出,所有其他随机生成的序列都被丢弃。这样,函数就会不断循环,直到以很小的概率生成唯一的正确字符串。
另一个想法是生成所有可能的排列,然后消除那些错误的排列,并从剩余的正确排列中随机抽取。但该算法的复杂度将是阶乘的。
最终的想法是对 Fisher-Yates 进行数学修改:从随机字符开始,然后每次绘制下一个字符时,将前一个字符被绘制的概率乘以衰减系数。例如,如果前一个字符已连续绘制了MaxConsecutiveRepetition多次,则衰减系数应变为0,以确保下一个字符不能与前一个字符相同。然而,我不知道如何准确计算这个衰减系数以确保以相等的概率生成所有正确的排列。
我需要一个满足上面列出的两个要求的算法。
我想使用向量来收集一些生成的整数,直到运行时我才知道其中的数量。但是,我必须实现的接口需要返回一个本机指针,该指针应该由调用者释放。该向量将非常大,因此,为了避免复制,我执行以下操作:
std::vector<int>* const Collector = new std::vector<int>;
//Several Collector.push_back();s
int* ReturnPointer = Collector->data();
free(Collector);
return ReturnPointer;
Run Code Online (Sandbox Code Playgroud)
上面的代码旨在避免向量的解构,这将释放我必须返回的数据指针 - 并且向量控制器本身也被释放。
我的问题是:这个技巧安全吗?或者有更好的解决方案吗?
重要提示:完整的架构不在我的控制范围内。我不允许返回本机指针以外的其他内容,也不允许调用者更改其调用代码。也就是说,我无法返回该向量。
我知道释放新指针是不好的。那么该怎么办:
std::vector<int>* const Collector = (std::vector<int>*)malloc(sizeof(std::vector<int>*));
*Collector = std::vector<int>;
//Several Collector.push_back();s
int* ReturnPointer = Collector->data();
free(Collector);
return ReturnPointer;
Run Code Online (Sandbox Code Playgroud)
这次我释放了malloced指针,这样可以吗?