从输入的数字中删除k个数字后如何获得最少的数字

Adi*_*wal 2 c algorithm data-structures

例如,如果输入的数字是24635,则23删除任何3位数后的最小数字.

它与取两个最小的数字不同,因为必须保持数字的顺序.

IVl*_*lad 19

删除k数字意味着保留n - k数字,其中n是总位数.

使用您按升序排序的堆栈.只要您仍然可以将n - k数字设置为数字并且当前元素小于堆栈顶部,则可以从中删除元素:

push(2) => 2
push(4) because 2 < 4 => 24
push(6) because 4 < 6 => 246
pop() because 3 < 6 and we can still end up with 2 digits => 24
pop() for the same reason => 2
push(3) => 23
push(5) => 235
Run Code Online (Sandbox Code Playgroud)

然后只取第一个k数字=> 23.或者你可以确保永远不要超过k数字,然后最后的堆栈是你的解决方案.

请注意,如果这意味着您将无法构建k数字解决方案,则无法弹出元素.为此,您需要检查堆栈中当前的元素数以及输入数字上当前位置右侧的位数.

伪代码:

stack = []
for each d in digits:
  while !stack.empty() and d < stack.top() and (*):
    stack.pop()

  if stack.size() < n - k:
    stack.push(d)

 (*) - exercise, fill in the condition that prevents you 
       from popping elements if you still want to be able to get to a solution.
 Hint: count how many elements the for loop went over already
       and see how many are left. Also consider how many you have left in the stack.
Run Code Online (Sandbox Code Playgroud)

由于每个元素最多进入和离开堆栈一次,因此复杂性是O(n).

  • 正如一般公告一样,[IVlad](http://stackoverflow.com/users/270287/ivlad)正好采用大O符号.在最坏的情况下,该算法执行2n-1比较,因此是*O(n)*时间. (4认同)
  • @JonathanMee - 不,实际上是正确的.首先,"O(n)"并不意味着每个元素只被认为******,这意味着每个元素只被认为是**常数**.在我的例子中,这个常数大约是2.对于输入中的任何数字,只会将其与堆栈中的元素进行比较.实际上,我们可能会遇到与堆栈中所有元素进行比较的情况,但之后我们也会在此之后清空堆栈,这样可以减少将来的工作.将它看作是访问(插入/删除)堆栈中每个元素的次数,您将看到它是"O(n)". (3认同)