删除数字的下位数

时间:2016-01-12 23:04:51

标签: algorithm language-agnostic

给出 x 数字 n 的数字。如何删除 y 数字,其余数字会产生更大的数字?

示例:

1)x=7  y=3
n=7816295
  -8-6-95
         =8695

2)x=4  y=2
n=4213
  4--3
      =43

3)x=3  y=1
n=888
     =88

只是陈述: x> y> 0

4 个答案:

答案 0 :(得分:2)

对于要删除的每个数字:从左到右迭代数字;如果您发现的数字小于右侧的数字,请将其删除并停止,否则删除最后一位数字。

如果位数x大于数字的实际长度,则表示存在前导零。由于这些将是第一个去的,您可以简单地将计数y减少相应的数量。

这是Python中的工作版本:

def remove_digits(n, x, y):
    s = str(n)
    if len(s) > x:
        raise ValueError
    elif len(s) < x:
        y -= x - len(s)
    if y <= 0:
        return n
    for r in range(y):
        for i in range(len(s)):
            if s[i] < s[i+1:i+2]:
                break
        s = s[:i] + s[i+1:]
    return int(s)

>>> remove_digits(7816295, 7, 3)
8695
>>> remove_digits(4213, 4, 2)
43
>>> remove_digits(888, 3, 1)
88

我犹豫要提交这个,因为它看起来太简单了。但我无法想到一个不起作用的案例。

答案 1 :(得分:1)

如果x = y,我们必须删除所有数字。

否则,您需要在前y + 1位找到最大数字。然后删除此最大数字前的所有y0元素。然后你需要将最大值添加到答案中,然后再次重复该任务,但现在需要删除y-y0元素。

在最坏的情况下,直接执行将在O(x ^ 2)时间内工作。

但是,使用Segment Tree数据结构可以有效地在给定范围内找到最大值。在最坏的情况下,时间复杂度将为O(x * log(x))。

P上。 S.我刚刚意识到,在O(x)中也可以使用事实来解决,它只存在10位数(但算法可能有点复杂)。我们需要在给定范围[L,R]中找到最小值,但此任务中的范围将变为&#34;更改&#34;从左到右(L和R总是增加)。我们只需要将数字(每个数字1个)的10个指针存储到数字中的第一个位置,使得位置&gt; = L.然后,为了找到最小值,我们只需要检查10个指针。要更新指针,我们将尝试正确移动它们。

因此,时间复杂度为O(10 * x)= O(x)

答案 2 :(得分:1)

这是一个O(x)解决方案。它构建了一个索引,将(i,d)映射到j,最小的数字&gt;我这样n的第j位是d。使用此索引,可以在O(1)时间内轻松找到解决方案中最大的下一个数字。

def index(digits):
    next = [len(digits)+1] * 10
    for i in xrange(len(digits), 0, -1):
        next[ord(digits[i-1])-ord('0')] = i-1
        yield next[::-1]

def minseq(n, y):
    n = str(n)
    idx = list(index(n))[::-1]
    i, r = 0, []
    for ry in xrange(len(n)-y):
        i = next(j for j in idx[i] if j <= y+ry) + 1
        r.append(n[i - 1])
    return ''.join(r)

print minseq(7816295, 3)
print minseq(4213, 2)

答案 3 :(得分:1)

伪代码:

Number.toDigits().filter (sortedSet (Number.toDigits()). take (y))

Imho你不需要知道x。

为了提高效率,可以预先计算Number.toDigits()

digits = Number.toDigits()
digits.filter (sortedSet (digits).take (y))

根据语言和上下文,您输出数字并完成或必须再次将结果转换为数字。

使用Scala-Code代码:

def toDigits (l: Long) : List [Long] = if (l < 10) l :: Nil else (toDigits (l /10)) :+ (l % 10)

val num = 734529L
val dig = toDigits (num)
dig.filter (_ > ((dig.sorted).take(2).last))

有序集是一个已排序的集合,这意味着每个元素只包含一次,然后生成的集合按某些条件排序,例如数字升序。 =&GT; 234579.

我们取两个(23)并从该子集中取最后一个(3)并按标准过滤数字,数字必须大于该值(3)。

你的问题没有明确说明,每个数字只包含原始数字一次,但由于你没有给出一个标准,哪一个有疑问,我把它当作一个隐含的假设。

其他语言当然可以有其他表达式(x.sorted,x.toSortedSet,new SortedSet(num),...)或缺少某些类,函数,您必须自己构建。

你可能需要编写自己的过滤方法,它采用一个小数P和一个集合C,并返回一个满足P的所有元素的新集合,P是一个接受一个T并返回一个布尔值的方法。非常有用的东西。