牛客网XM26最大新整数

最大新整数

http://www.nowcoder.com/questionTerminal/827e316ddc824cb6ac6825c1f720ed02


牛客网XM26最大新整数

题目描述

有一十进制正整数,移除其中的 K 个数,使剩下的数字是所有可能中最大的。
假设:
字符串的长度一定大于等于 K
字符串不会以 0 开头

输入描述:

一行由正整数组成的数字字符串,和一个正整数 K,两个数据用空格隔开,如:1432219 3
字符串长度不超过2000K<=2000

输出描述:

移除 K 位后可能的最大的数字字符串。
1432219 移除 1, 2, 1 3 个数字后得到 4329,为所有可能中的最大值。

示例1

输入

1432219 3

输出

4329

解题思路

拿到这个题首先想到的问题是:如何能保证数字的高位更大?

假设K==1

一眼就能看到应当删除最高位的1,得到432219。这个时候问题简化成删除某一位数字使结果数值达到最大,也就是求前N位中第一个最小值,然后删除它。示例1中,最高位的1,即是最小的值。

考虑另一种用例,4444129,删除前四位中任一个,结果都是444129;当看到第5位时,结果变成了444429。看到这里时,“感觉“问题变成了在前N位中求第一个最小值。

假设K==2

K2时,情况变得复杂一些了。

对于示例1,我们先按K==1的情况删除一位1。我们在余下的数字(432219)中再按k=1来求最小值,得到需要删除的数字,发现余下的数字中仍然是1最小,删除1得到43229

假设K==3

K3时,仍然在上一步的基础上,删除最小值,得到4329。与答案吻合。

分析到这里,代码可以初步写出来了。

def func(s, K):
    k = int(K)
    while k > 0:
        index = 0
        to_delete = s[0]
        for idx, num in enumerate(s):
            if num < to_delete:
                index = idx
                to_delete = num
        s = (s[:index] + s[index + 1:])
        k -= 1
    return s
if __name__ == '__main__':
    print(func('1432219','3'))


代码对于示例能够成功执行,但是很不幸,只能通过7/20个用例。对于这个用例,41681991713273619813 10,预期输出是9977619813,实际输出是4689977698。

再回过头来看解题思路,偏离了使最高位最大的主旨,代码变成了求最小值。上面的代码还有另外一个问题,代码复杂度为O(n2),可能会超时。

怎么样能够使高位相对最大呢?有一种算法能够很好的支撑这种目标单调栈。

单调栈的定义

在一个栈里面存放的数据都是有序的。

如果是升序排列,为单调递增栈

如果是降序排列,为单调递减栈

单调栈的性质

能快速地得知当前位置左()侧比他大(或小)的数据的位置,时间复杂度是O(1)

举例

求解数组中元素右边第一个比它小的元素的下标,从前往后,构造单调递增栈;
求解数组中元素右边第一个比它大的元素的下标,从前往后,构造单调递减栈;
求解数组中元素左边第一个比它小的元素的下标,从后往前,构造单调递减栈;
求解数组中元素左边第一个比它小的元素的下标,从后往前,构造单调递增栈。


最终代码:
def func(s, K):
    k = int(K)
    stack = []

    for idx, num in enumerate(s):
        # 避免无效循环,K为0时退出
        if k == 0:
            break
        while stack and num > stack[-1] and k > 0:
            stack.pop()
            k -= 1
        stack.append(num)
    
    result = (''.join(stack) + (s[idx + 1:] if idx == len(s) - 1 else s[idx:]))
    # 这里加了特判,有可能 k会大于0
    if k > 0:
        return result[:len(s) - int(K)]
    return result


if __name__ == '__main__':
    s, K = input().strip().split()
    print(func(s, K))

由于格式问题,建议查看公众号文章,传递门


全部评论

相关推荐

joe2333:怀念以前大家拿华为当保底的日子
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务