仅使用允许的数字构建大于K的最小数字

时间:2015-04-23 11:29:32

标签: algorithm language-agnostic

给定一个包含0-9和数字K之间的数字的数组,找到由数组中的数字构建的最小数字,使其大于K

例如,如果array = [0,1]K = 21,则该计划应返回1000110小于21100是仅由zerosones组成的第一个数字,大于21

我可以考虑一下蛮力方法,在那里我可以找到所有可能用数组中的数字创建的数字,然后找到大于K的最小数字,但我正在寻找一个更聪明和优雅的解决方案。你有什么建议吗?

3 个答案:

答案 0 :(得分:0)

你能建立一个与给定数字相等的数字,除了最后一个更大的数字,是吗?

不是吗?那么,你可以建立一个与给定数字相等的数字,除了那个更大的十位数吗?

等等...

答案 1 :(得分:0)

<强>算法:

让我介绍一些变量:

k_digits - 数字K中的位数。

首先,我们可以观察到生成的数字会有k_digitsk_digits + 1。如果还不清楚的话,我最后会详细解释。

让我们假设答案会有k_digit个数字。

我们可以将主要问题分成几个较小的(然后通过将解决方案与子问题相结合来获得初始问题的答案)。子问题的陈述听起来如下:

  
      
  1. 最小数字大于K 没有最后一位数。
  2.   
  3. 我们可以编号K而不是我们允许使用的数字的最后一位数吗?
  4.   

让我们假设我们有解决这个问题的方法。然后我们需要找到最初问题的答案。我们可以通过以下方式执行此操作:

a)如果子问题2的答案为真(我们可以在没有最后一位数的情况下编写)。然后我们应该尝试将集合中最小的可用数字添加到该数字的末尾,使其大于K。我们实际上做了什么 - 我们尝试用K中较大的一个替换最初allowed set的最后一个数字。我们称之为新号码 answer1

b)将集合中的最小可用数字添加到第一个子问题的数字末尾。由于其前缀较大,此数字将大于K。我们将此号码称为answer2

c)在最后一步,我们应该比较answer1(如果存在)和answer2,并选择最小的。这将是最初问题的答案。

嗯,现在我希望我们很清楚如何结合子问题的答案。 那么,现在我将解释如何找到子问题的解决方案。

让我们从第二个子问题开始。这很容易 - 我们只是检查我们的allowed set数字K的所有数字(不包括最后一位)是否都有。

现在第一个子问题。您可能会注意到此子问题与初始问题相同,但K较小。所以,我们可以递归地解决这个问题&#34;。这里的基本案例将是一位数K。当我们只有一位数字时,我们可以直接说出答案 - 只需要搜索我们的数据集,使其大于K的数字。

另外,请注意,在某些时候我们可能没有子问题1的答案。这意味着我们无法组成大于k_digits的长度K。但是,在这种情况下,我们总是可以使用k_digits + 1来编号。只需从允许的集(k_digits + 1)次中选择最小的数字。 特例:零。

示例:

allowed_set=[4,5]
K = 435

我们可以看到我们可以将我们的初始问题吐到子问题,其中K = 43。 第二个子问题的解决方案是false,因为我们不允许使用数字3。我们将尝试以下列方式找到第一个子问题的解决方案 - 再次将其拆分为两个子问题,其中K = 4。在这种情况下,第一个子问题的答案为5,第二个子问题的答案为4。我们可以将案例K = 43的答案组成如下:answer1 = 44answer2 = 54answer1较小,因此,这实际上是K = 43时案例的答案。然后,要查找K = 435的答案,我们只能将4添加到44的末尾。所以答案是444

这可能不是最好的例子,但我希望它能说明我的答案。如果您有任何其他意见,请询问。

答案 2 :(得分:0)

我自己编程很新,大约有4个月的C ++经验,我们被赋予了与此相似的作业作为我们的作业问题之一,希望这有帮助!

//given array A of usable digits and assuming it is sorted
//meaning A[1] is the smallest

ans = 0;

//first we find the digits of K
//we use {} as Gauss
K_digits = {log(K)} + 1
numleft = K;
for i = 1 to K_digits
    B[i] = {numleft/(10^(K_digits - i))}
    numleft = numleft - B[i]*10^(K_digits - i)

//next we search through the array K_digits times
Max_seq = A[A.length] // max number in array
min_seq = A[1] // min number in array
usebigger = 0  // if this equals 1, we need to add an extra digit than K to be larger than K
copy = 0 //number of digits to copy, starting from left side

j = 1
while (j <= K_digits)
    if Max_seq < B[j]
        usebigger = 1
        j = K_digits + 1 // end while loop
    else if Max_seq == B[j]
        copy = copy + 1
        j = j + 1
    else if Max_seq > B[j] 
        for t = 1 to A.length
            if B[j] < A[t]
            value = A[t]
            break;
        j = K_digits + 1

if copy == K_digits // can only manage to find a same valued number
    usebigger = 1


//finally, with this info, we find the answer
if usebigger == 1 // need to add an extra digit than K to be larger than K
    if min_seq == 0
        for s = 1 to A.length
            if A[s] > 0
            min_num = A[S]
            break;
        ans = min_num*(10^K_digits)
    else
        for x = 0 to K_digits
            ans = ans + min_seq*(10^x)    

else
    if copy != 0
        for i = 1 to copy
            ans = ans + B[i]*(10^(K_digits - i))
    ans = ans + value*(10^(K_digits - copy - 1))

    if copy+2 <= K_digits
        for y = copy+2 to K_digits
            ans = ans + min_seq*(10^(K_digits - y))

return ans