最长的数组的数字子序列

时间:2017-12-05 14:12:56

标签: algorithm recursion dynamic-programming

我们在课程中遇到了这个问题,没有人和我谈过这个问题。我想要一些帮助。所以这就是问题所在:

设A是长度为n的数组,其中包含n个数字(数字在0-9之间)。 A 的数字子序列是一个正数序列,当序列中某个数字的所有数字出现在A中的一行时,它们的数字构成A的子序列。

例如:序列13,1,345,89,23是输入数组A的数字子序列: [ 1 3 下,如图5所示, 1 下,如图2所示, 3 4 下,的 5 下,的 8 下,的 9 下,4,5,的 2 3 ] < / p>

数字子序列的长度是其中出现的数字量(在上例中:5) 如果序列中的每个数字都大于它之前的数字,则数字子序列增加

请求是在动态编程方法中找到一种算法(基于递归公式),该算法找到输入数组A中增长最长的数字子序列。

提前感谢所有帮助者!

1 个答案:

答案 0 :(得分:1)

查看数组中的第一个数字。这个数字不是您的数字序列中的数字的一部分,也可能是。如果是,则该数字可以具有1,2,...,n个数字。对于每次猜测,请返回:

  • 不在数字中:return f(array[2...n], -1)
  • 1位数的第1位数:返回array[1] union f(array[2...n], number(array[1]))
  • 2位数字的第1位数字:返回array[1...2] union f(array[3...n], number(array[1...2]))
  • 3位数字的第1位数字:返回array[1...3] union f(array[4...n], number(array[1...3]))
  • ...
  • n位数的第一位数:return array[1...n]

您可以在此处进行一些优化,以便在此过程中省略一些步骤。

  • f(array[1...k], x) = f(array[1...k], y)如果给定假设的最后一个数字xy的序列中下一个数字的最小选择是相同的。因此,如果array[1...k]xy的下一个数字的最小选择相同,那么我们已经为f计算了x的值,我们可以将该值重用于y

  • f(array[1...k], x) = c + f(array[2...k], x)每当array[1] = 0,其中c = 1 x < 0c = 0 x >= 0。也就是说,我们可以忽略前导零,除了可能在数组开头的前导零,应始终选择为我们的第一个一位数。

  • 在决定数字是否为k - 位数字的第一个数字时,如果您从未选择前导零,则您知道序列中剩余数字的上限按n/k,因为在此之后选择的任何数字都需要至少k位数。如果你还记得你迄今为止看到的最长的序列,那么你就可以发现那些没有希望做得比你所看到的更好的路径并忽略它们。

  • 如果一个数组中至少有k(k+1)/2个非零数字,则数字序列的长度至少为k,取数字为1,2,...... ,k从零到左依次为非零数字。因此,如果您预先计算此值,则可以立即避开某些路径。

这里讨论了优化的粗略伪代码:

solve(array[1...n])

    z = number of non-zero entries in array
    last_number = -1
    min_soln = floor((sqrt(1 + 8z) - 1) / 2)
    return solve_internal(array[1...n], min_soln, last_number)



memo = {}

solve_internal(array[1...n], min_soln, last_number)

    // ignore potentially leading zeroes except the first one
    if array[1] = 0 then
        if last_number < 0 then
            return {0} union solve_internal(array[2...n], min_soln - 1, 0)
        else then
            return solve_internal(array[2...n], min_soln, last_number)

    // abort since we don't have enough digits left to get a solution
    if floor(n / #digits(last_number)) < min_soln return []

    // look up current situation in previous partial solutions
    z = smallest number formable in array greater than last_number
    if memo contains (n, z) then
        return memo[n, z]

    soln = {}
    for k = 1 to n do
        soln_k = solve_internal(array[k+1...n], min_soln - 1, array[1...k])
        if |soln_k| > |soln| then
            soln = soln_k
            min_soln = |soln|

    memo[n, z] = soln
    return soln