【问题标题】:Find the maximum K digit number formed by a given number while preserving the order在保留顺序的同时找到由给定数字组成的最大 K 位数字
【发布时间】:2015-12-29 18:04:28
【问题描述】:

给定一个数字,我们必须在保留顺序的同时找到最大的“K”位数字(“K”位数字将是一个子序列)。

Input : The number 'n' and number of digits you should pick up to form the answer 'K'
Output : The maximum formed K digit number

例子:

Input : n = 912583, k=3
Output : 983

【问题讨论】:

  • 很好的问题,但你的问题是什么?
  • 你的尝试在哪里?
  • @Henry 问题是找到给定 K 的 K 位数。
  • @Ignacio Vazquez-Abrams 我试过了,但我无法提出解决方案。所以我想从别人那里得到帮助。

标签: algorithm dynamic-programming greedy


【解决方案1】:

您实际上并不需要动态规划来解决这个问题。最大的 K 位数将始终从可能的最大数字开始,并且始终最好选择可能出现的最大数字的最早出现,因为这样可以为剩余的数字留下最多的选项。

同样,最好的第二个数字是最早出现的最大可能的第二个数字,依此类推,直到您完成为止。

当局部最佳选择(例如最早出现的最大可能数字)并不总是全局最佳选择时,使用动态编程。

【讨论】:

  • 并非总是如此;最大的数字后面可能没有足够的数字来组成 K 位数字。
  • “最大可能数字”是指留下足够数字的最大数字
  • 哦,好的。不过,如果你愿意,你可以使用 dp 。选择第一个数字,丢弃直到所选数字的数字,递归 K-1...
  • @m69,这不是动态编程
  • 你说得对,事实并非如此。如果您绝对想使用 dp,则可以向后执行,但这没有多大意义。
【解决方案2】:

这是我的解决方案,所以这里有一个代码答案(我发现这个问题很有趣,可以解决)。基本上我只是找到第一个最大的数字,它仍然有足够的尾随数字来填写必要的长度,然后在第一个最大数字之后递归地重复这个问题(基本上是 Matt Timmermans 建议的)。我对此进行了一些测试,所以我认为它是完整的并且没有任何明显的错误,但我可能肯定错过了一个边缘案例。

我意识到这可能不是我能做出这个算法的最快算法,因为我正在做很多从 int 到 string 和 back 的变量转换,但由于它是一个相对较小的输入大小,我想我不会担心除非有人要我这样做。

注意:如果输入没有意义,例如请求的长度比输入长,它会返回 0。

private int GetMaximumNumber(int input, int length)
{
    input = Math.Abs(input);
    var maximumNumber = 0;
    var inputString = input.ToString();
    if (length > inputString.Length || length < 1)
        return maximumNumber;

    var indexOfMaxDigit = FindMaximumDigit(input, length);

    var maxDigit = int.Parse(inputString.Substring(indexOfMaxDigit, 1));
    if (length > 1)
        maximumNumber = (maxDigit * (int)(Math.Pow(10.0, (double)length-1))) + GetMaximumNumber(int.Parse(inputString.Substring(indexOfMaxDigit + 1)), length - 1);
    else
        maximumNumber = maxDigit;

    return maximumNumber;
}

private int FindMaximumDigit(int input, int length)
{
    var indexOfMaxDigit = -1;
    var inputSubstring = input.ToString().Substring(0, input.ToString().Length - length + 1);
    for (var i = 9; i > -1; i--)
    {
        indexOfMaxDigit = inputSubstring.IndexOf(i.ToString(), StringComparison.Ordinal);
        if (indexOfMaxDigit != -1)
            break;
    }

    return indexOfMaxDigit;
}

【讨论】:

    【解决方案3】:

    可以通过动态规划来解决。您需要状态dp[i][j],这是您从第一个i-1 数字中选择j 数字时的最佳值。然后就可以解决了:

    void solve(int n, int k) {
        string str = string(n);
        int dp[32][32];
        memset(dp, 0, sizeof(dp));
        for (size_t i = 0; i < str.length(); ++i) {
            dp[i + 1][1] = max(dp[i][1], str[i] - '0');
            for (size_t j = 2; j <= k; ++j) {
                dp[i + 1][j] = max(dp[i][j - 1] * 10 + str[i] - '0', dp[i][j]);
            }
        }
    
        cout << dp[str.length][k];
    }
    

    【讨论】:

    • 希望我只需要调整我的反讽检测器。
    【解决方案4】:

    我在解决https://leetcode.com/problems/create-maximum-number/description/ 时偶然发现了这一点(这是解决方案的一部分),正如马特在他的回答中指出的那样,贪婪的策略就足够了。这是带有驱动程序的完整 C++ 程序。 n = 78859 和 k = 3 输出 889

    #include <algorithm>
    #include <iostream>
    #include <iterator>
    #include <vector>
    
    using namespace std;
    
    template <typename IIT, typename OIT>
    void
    MaxNumPreservingOrder(IIT first, IIT last, OIT output, int k) {
        if (k == 0)
            return;
        auto N = distance(first, last);
        if (N == k) {
            copy(first, last, output);
            return;
        }
        auto it = first;
        while (k > 0)  {
            auto maxval = *max_element(it, last - k + 1);
            it = find(it, last - k + 1, maxval);
            *output = *it;
            ++output;
            ++it;
            --k;
        }
        return;
    }
    
    int
    main(void) {
        vector< int > v = {7, 8, 8, 5, 9}, o;
        int k = 3;
        o.reserve(k);
        MaxNumPreservingOrder(begin(v), end(v), back_inserter(o), k);
        copy(begin(o), end(o), ostream_iterator< int >(cout, " "));
        cout << "\n";
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-24
      • 2014-07-29
      • 2021-05-12
      • 1970-01-01
      • 2019-06-04
      • 1970-01-01
      • 1970-01-01
      • 2012-11-20
      相关资源
      最近更新 更多