4.2 京东算法笔试-递增子序列的最少删除个数

题目描述:

小明有一个长度为 n 的正整数序列,序列中每个数字都在范围[1,K]内。小明现在想要删除这个序列中的若千数字,使得这个序列的最长上升子序列的长度严格小于 k。他现在想知道:最少需要删除多少个数字?

题解:如果有帮助的话,求个赞谢谢~



注:这题确实难度非常大,oj时并没有完全跑通,实现起来有点复杂,欢迎大家提出更好的实现
此外,问题转化后,与LeetCode中的《使字符串平衡的最少删除次数》是类似的,上面说的双指针解法并不能保证是最少的次数,下面的实现已经更新为枚举法,也可以用动态规划来解,具体解法参考LeetCode中的那道题即可。



import sys
from sortedcontainers import SortedDict
import bisect

m = int(input())

def get_ans(a,b):
    if not a or not b:
        return 0
    mincout = float('inf')
    for i in range(len(a)):
        index = bisect.bisect(b, a[i])
        mincout = min(mincout, i+len(b)-index)
    for j in range(len(b)):
        index = bisect.bisect(a, b[j])
        mincout = min(mincout, len(b)-1-j+index)
    return mincout

for _ in range(m):
    N, K = [int(s) for s in input().strip().split()]
    nums = [int(s) for s in input().strip().split()]

    # 数值范围在[1.k],所以不可能有长度超过k的递增子序列,最长就是k
    # 要保证每一层均是长度为k的路径上的结点
    dic = SortedDict({})
    for i in range(len(nums)):
        if nums[i] not in dic:
            dic[nums[i]] = []
        flag = 1
        for j in range(1,nums[i]): # 需要过滤比如23 123中第一个23这种无效结点的情况
            if j not in dic:
                flag = 0
                break
        if flag:
            dic[nums[i]].append(i)

    for i in range(K-1, 0, -1): # 需要过滤比如123 12中第二个12这种无效结点的情况
        if i in dic:
            if i+1 in dic:
                while dic[i] and dic[i+1] and dic[i][-1] > dic[i+1][-1]:
                    del dic[i][-1]
    
    if len(dic.keys()) != K: # 最长递增子序列长度不是k的时候,就不需要删除了,比如12122 k=3的情况
        print(0)
        continue

    minans = N
    for k, v in dic.items(): # 对每一层进行双指针判断最少删除结点,使得层断开连接
        if k+1 in dic:
            alist = v
            blist = dic[k+1]
            ans = get_ans(alist, blist)
            minans = min(minans, ans)
    print(minans)

测试样例

答案分别是:1  5  2  2  1  1  1  0  2 2
带括号的是需要删除的数
10

5(N) 3(K)
1 (2) 3 1 2

5 1
1 1 1 1 1

10 4
1 (2) 1 (2) 3 4 3 3 4 4

9 3
(1) 2 2 1 1 3 (2) 3 3

8 4
4 3 (1) 2 3 2 4 3

8 5
(1) 2 3 2 1 3 4 5

14 3
(1) 2 2 1 1 3 3 2 1 1 2 1 1 2

4 3
2 3 1 2

9 3
1 (2) 1 3 1 3 2 2 (3)

5 2
1 1 1 (2) (2)




#京东笔试##内推##春招##实习##笔试题目#
全部评论
哥们图里有水印,还是把图删了打字吧,不能拍题
点赞 回复 分享
发布于 2022-04-02 22:45
大佬,第二题粉刷的做了吗
点赞 回复 分享
发布于 2022-04-02 22:54
点赞 回复 分享
发布于 2022-04-02 23:53
太牛了
点赞 回复 分享
发布于 2022-04-03 00:27
当我动归完之后就说我超时我就没往下做了
点赞 回复 分享
发布于 2022-04-03 10:11
@sunnyangBoy 这个 if i + 1 == len(a) -1&nbs***bsp;j - 1 == -1: 是不是应该改成 if i + 1 == len(a) &nbs***bsp;j - 1 == -1:?好像会越界
点赞 回复 分享
发布于 2022-04-03 14:23
但是如果测试样例是5 2 (1 1 1 2 2)应该是输出2,但是你这边好像输出的3。
点赞 回复 分享
发布于 2022-04-03 16:32
我怎么记得笔试的时候,系统是不带sortedcontainers这个library的
点赞 回复 分享
发布于 2022-04-03 18:01
请问一下可以解释一下get_ans里面的两个for循环是什么意思吗,没看懂
点赞 回复 分享
发布于 2022-04-03 22:21
我来举个反例 n=11 k=3 nums=[1,2,3,2,3,2,1,2,1,2,3] 输出答案是3 实际删除第一个1和最后一个3就行了 答案应该为2
点赞 回复 分享
发布于 2022-05-29 14:33

相关推荐

评论
21
37
分享

创作者周榜

更多
牛客网
牛客企业服务