求解将数字N转为K所需的最小交换、末尾增删数字操作次数
解法思路
核心前提:先理清楚三类操作的特性
- 删除只能操作数字末尾,所以删除k次后剩余的一定是原数字交换后的前
len(N)-k位(可以先通过交换把需要保留的数字挪到前缀,不需要的挪到后缀删除) - 新增只能操作数字末尾,所以最终数字的前缀就是保留的m位调整后的结果,后缀是新增的内容
- 交换可以调整任意两位的位置,只要两个数字集合的频率完全一致,就能通过交换得到任意排列
最小操作数推导
我们设保留的公共前缀长度为m(m最大不超过min(len(N), len(K))),总操作数可以拆成三部分:
- 删除次数:
len(N) - m,把N末尾不需要的len(N)-m位删掉 - 新增次数:
len(K) - m,在末尾补len(K)-m位得到K的长度 - 交换次数:将保留的m位排列为K前m位的最少交换次数,等于
(排列总长度 - 循环分解的循环节数量),这里排列总长度是N的长度,因为交换是对原N所有位操作,把需要的m位挪到前缀并排成目标顺序,不需要的位随便放后缀即可
因为m每增大1,删除+新增的总次数就减少2,而交换次数最多增加1,所以最大的可行m对应的总操作数一定是最小的,我们只需要从大到小遍历m,找到第一个可行的m即可。
可行m的判断规则
m可行的条件是:K的前m位中每个数字的出现次数,都不超过N中对应数字的出现次数。
无需额外数组存储频率,直接遍历0-9每个数字,分别统计N中的总出现次数、K前m位的出现次数,逐一比对即可,全程只用到临时计数器变量,符合无额外内存开销的要求。
示例验证
以f(1234, 4326)为例:
- N转字符串为
"1234"长度4,K转字符串为"4326"长度4 - 先试最大m=4:K前4位含数字6,N中没有6,不可行
- 再试m=3:K前3位是
"432",数字4、3、2在N中各出现1次,满足频率要求,是最大可行m - 计算操作数:删除次数1 + 新增次数1 + 交换次数2 = 4,和示例结果一致
内容的提问来源于stack exchange,提问作者Paul Keseru
相关产品推荐
相关产品推荐

