删除数字的低位数字
Remove the inferior digits of a number
给定一个数字 n,共 x 个数字。如何删除 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。
如果 x = y 我们必须删除所有数字。
否则,您需要在前y + 1 位数字中找到最大数字。然后删除这个最大数字之前的所有 y0 元素。然后您需要将该最大值添加到答案中,然后再次重复该任务,但您现在需要删除 y - y0 个元素。
在最坏的情况下,直接实施将在 O(x^2) 时间内工作。
但是使用线段树数据结构可以有效地找到给定范围内的最大值。在最坏的情况下,时间复杂度将为 O(x * log(x))。
P. S. 我刚刚意识到,也有可能在 O(x) 中解决,使用仅存在 10 位数字的事实(但算法可能有点复杂)。我们需要找到给定范围 [L, R] 中的最小值,但此任务中的范围将从左到右 "change"(L 和 R 始终递增)。我们只需要存储 10 个指向数字的指针(每个数字 1 个)到数字中的第一个位置,使得位置 >= L。然后为了找到最小值,我们只需要检查 10 个指针。为了更新指针,我们将尝试将它们向右移动。
所以时间复杂度为O(10 * x) = O(x)
这是一个复杂度为 O(x) 的解决方案。它建立一个索引,将 (i, d) 映射到 j,最小的数字 > i 使得 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)
伪代码:
Number.toDigits().filter (sortedSet (Number.toDigits()). take (y))
恕我直言,您不需要知道 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))
有序集合是经过排序的集合,这意味着每个元素只包含一次,然后生成的集合按某些标准排序,例如数字升序。 => 234579。
我们从其中两个 (23) 中取出最后一个 (3) 并根据标准过滤数字,即数字必须大于该值 (3)。
你的问题没有明确说明,每个数字在原始数字中只包含一次,但由于你没有给出标准,不确定要删除哪一个,我将其视为隐含的假设。
其他语言当然可能有其他表达式(x.sorted, x.toSortedSet, new SortedSet (num), ...)或缺少某些 类, 函数,你会必须自己建造。
您可能需要编写自己的过滤方法,它采用谓词 P 和集合 C,以及 returns 满足 P 的所有元素的新集合,P 是采用一个 T 的方法returns 一个布尔值。非常有用的东西。
对于要删除的每个数字:从左到右遍历数字;如果你发现一个数字小于它右边的数字,删除它并停止,否则删除最后一个数字。
如果位数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
我犹豫要不要提交这个,因为它看起来太简单了。但是我想不出它不起作用的情况。
给定一个数字 n,共 x 个数字。如何删除 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。
如果 x = y 我们必须删除所有数字。
否则,您需要在前y + 1 位数字中找到最大数字。然后删除这个最大数字之前的所有 y0 元素。然后您需要将该最大值添加到答案中,然后再次重复该任务,但您现在需要删除 y - y0 个元素。
在最坏的情况下,直接实施将在 O(x^2) 时间内工作。
但是使用线段树数据结构可以有效地找到给定范围内的最大值。在最坏的情况下,时间复杂度将为 O(x * log(x))。
P. S. 我刚刚意识到,也有可能在 O(x) 中解决,使用仅存在 10 位数字的事实(但算法可能有点复杂)。我们需要找到给定范围 [L, R] 中的最小值,但此任务中的范围将从左到右 "change"(L 和 R 始终递增)。我们只需要存储 10 个指向数字的指针(每个数字 1 个)到数字中的第一个位置,使得位置 >= L。然后为了找到最小值,我们只需要检查 10 个指针。为了更新指针,我们将尝试将它们向右移动。
所以时间复杂度为O(10 * x) = O(x)
这是一个复杂度为 O(x) 的解决方案。它建立一个索引,将 (i, d) 映射到 j,最小的数字 > i 使得 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)
伪代码:
Number.toDigits().filter (sortedSet (Number.toDigits()). take (y))
恕我直言,您不需要知道 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))
有序集合是经过排序的集合,这意味着每个元素只包含一次,然后生成的集合按某些标准排序,例如数字升序。 => 234579。
我们从其中两个 (23) 中取出最后一个 (3) 并根据标准过滤数字,即数字必须大于该值 (3)。
你的问题没有明确说明,每个数字在原始数字中只包含一次,但由于你没有给出标准,不确定要删除哪一个,我将其视为隐含的假设。
其他语言当然可能有其他表达式(x.sorted, x.toSortedSet, new SortedSet (num), ...)或缺少某些 类, 函数,你会必须自己建造。
您可能需要编写自己的过滤方法,它采用谓词 P 和集合 C,以及 returns 满足 P 的所有元素的新集合,P 是采用一个 T 的方法returns 一个布尔值。非常有用的东西。
对于要删除的每个数字:从左到右遍历数字;如果你发现一个数字小于它右边的数字,删除它并停止,否则删除最后一个数字。
如果位数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
我犹豫要不要提交这个,因为它看起来太简单了。但是我想不出它不起作用的情况。