【问题标题】:Find largest permutation less than a certain value找到小于某个值的最大排列
【发布时间】:2018-06-27 00:54:57
【问题描述】:

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

给定两个整数 ab,找出最大的 a 小于 b 的数字的排列。

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

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

我非常感谢任何形式的帮助。非常感谢你们!

【问题讨论】:

    标签: c++ string algorithm dynamic-programming


    【解决方案1】:

    您无需找到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 的位数多于b,则a 的排列总是大于b(现在假设a 中没有0)。然后你知道没有解决方案。如果a 的位数少于b,只需找到a 的最大排列,因为a 永远不会大于b。如果它们的长度相同,则与按字典顺序执行相同。
    • 如果a中有0,则删除它们,直到用完0或ab的位数相同,然后继续上述过程。跨度>
    • 好的,谢谢...我只是接受你的回答,虽然它在技术上在你的 cmets XD 中非常感谢你!!
    • 刚刚编辑了答案以反映更改。很高兴为您提供帮助!
    【解决方案2】:

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

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

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

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

    • 去掉 b 的前导零,这会让事情变得更简单。

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

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

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

    【讨论】:

    • 嗯,抱歉,我认为我的问题表述有误,我将对其进行编辑。
    • 现在它是整数而不是字符串。我将如何解释数字的长度?例如 215 > 52 但 52 按字典顺序小于 215...
    【解决方案3】:

    同意之前的回答 这是一段使用基于 std::set 的 bag-of-char 表示的代码

    #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;
        }
    

    【讨论】:

      猜你喜欢
      • 2010-10-20
      • 1970-01-01
      • 1970-01-01
      • 2018-06-19
      • 1970-01-01
      • 1970-01-01
      • 2019-11-08
      • 1970-01-01
      • 2018-03-12
      相关资源
      最近更新 更多