查找小于特定值的最大排列

Find largest permutation less than a certain value

本文关键字:排列 小于 查找      更新时间:2023-10-16

这是一个我似乎不知道该怎么做的编程问题。

给定两个整数ab,找到最大的 小于ba数字排列。

有什么方法可以在c++中使用next_permutation功能吗?或者,我应该使用某种形式的动态编程来解决这个问题吗?

我尝试使用 next_permutation 函数测试a的所有排列,但由于整数的大小可以达到 10^18、18! 太大了,这不可行。有什么方法可以减少时间吗?如果没有,我应该如何使用动态规划来解决此类问题?

我将非常感谢对此的任何帮助。非常感谢你们!

您无需找到所有a组合即可执行此操作。

让我们假设a是"世界",b是"你好"。您可以在a中找到小于或等于b的第一个字符的最大字符。在这种情况下,您会在a中找到"d"。这是你可以从你的a排列开始的最大角色,所以你应该从它开始。因为"d"严格小于"h",所以你可以从大到小排列a所有剩余的字符,你会得到"dwrol"。

如果第一个字符相同,假设a是"世界",b是"喜欢",则继续处理第一个字符之后的其余字符a,并与b的第二个字符进行比较。在此示例中,您在a中选择的第一个字符是"l"。你还剩下"w"、"o"、"r"、"d"。然后,您选择小于"like"中第二个字符的最大字符,即"d",然后重复前面的过程并得到"ldwro"。

编辑:

对于编辑的问题(数字而不是字符的排列),想法是相同的。如果a的位数多于b,则a排列始终大于b(让我们假设现在a没有0)。然后你知道没有解决方案。如果a的位数少于b,只需找到 a 的最大排列,因为 a 永远不能大于b。如果它们的长度相同,则与按字典顺序执行相同。

如果a中有 0,只需删除它们,直到用完 0 或 a 与b的位数相同,然后继续上述过程。

遍历所有排列会花费太长时间。只是贪婪。

词典比较的情况很简单(这是问题的原始版本):

依次为每个位置,选择尚未使用的a的最大元素,这仍然使a在字典上小于b

数字有点复杂,因为比较数字的规则略有不同。幸运的是,它可以很容易地简化为词典比较。

  • b中剥离前导零,这将使事情更简单一些。

  • 如果ab的长度相等,则与前一种情况相同 - 词典比较与数值比较相同。

  • 如果b的长度小于a,只需将前导零添加到b以匹配a的长度 - 回到字典顺序比较。

  • 如果a的长度小于b,并且b没有前导零(我们只是去掉了它们)。这保证了a小于b。因此,我们可以通过从最大的数字开始对数字进行排序来选择最大的排列。

同意之前的答案 这是一段使用 std::set 的字符袋表示的代码

#include<iostream>
#include <set>
#include <string>
#include <algorithm>
std::string greatest_permutation(const std::string &s, const std::string &limit) {
std::string result;
std::set<char> bag;
std::copy(s.begin(), s.end(),
std::insert_iterator<std::set<char> >(bag, bag.begin()));
for (int j=0; j<limit.size(); ++j) {
std::set<char>::iterator i = bag.upper_bound(limit[j]);
if (i == bag.begin()) // no more chars available
return result;
else
result += *--i;
bag.erase(i);
}
return result;
}
int main() {
std::cout<<
greatest_permutation("abcdefghi", "cfhuiigwuioiiom")
<<std::endl;
}