题解 | #小红的数位删除#

小红的数位删除

https://www.nowcoder.com/practice/a1044c31930341d6a51c9a619254074a

本题的核心在于通过最少的删除操作,使得两个数字之间满足倍数关系(即 的倍数,或 的倍数)。

约束分析:

  • 数据范围: 。 这意味着数字的长度最大仅为 10位 ( 是最小的10位数,最大值接近 )。

  • 操作定义: 删除数位。这本质上是在寻找字符串的子序列 (Subsequence)

  • 目标函数: 最小操作次数。

    要使得操作次数最小,等同于要求保留下来的子序列长度之和最大

算法:子序列枚举与哈希映射

由于数字的最大位数为10,直接暴力搜索的空间非常小,这使得全量枚举(Generate and Check) 成为最稳健且高效的策略。

算法:暴力枚举 结合 哈希去重

虽然这是一个求“最小代价”的问题,理论上可以使用广度优先搜索 (BFS)。但在本题中,状态空间(所有可能的子数字对)非常有限。直接生成所有可能性并进行两两比对,在逻辑上比维护 BFS 的队列和状态去重更加简单直接,且常数开销更低。

算法可分解为三个主要步骤:

  1. 子序列生成 (Subsequence Generation): 分别生成 的所有非空子序列。这里需要通过二进制位掩码(Bitmask)或深度优先搜索(DFS)来遍历每一位是“保留”还是“删除”。

  2. 状态压缩与映射 (State Mapping): 由于不同的删除方式可能产生相同的数值(例如 "101" 删除中间的 '0' 得到 "11",删除末尾 '1' 得到 "10",删除首位 '1' 得到 "01" 即数值 1),我们需要记录每个数值对应的最大保留长度

    • 原因:对于相同的数值结果,保留的字符越多,删除操作越少,代价越低。
    • 数据结构:HashMap<Integer, Integer>,Key 为子序列原本的数值,Value 为该数值对应的最大子序列长度。
    • 注意:关于前导零(如 "01"),在本题逻辑中,如果 "01" 和 "1" 都代表数值 1,但 "01" 长度为 2,"1" 长度为 1,我们显然更倾向于保留 "01" 以减少删除次数。因此,映射时应取由该数值转换来的最大原始长度。
  3. 笛卡尔积检测 (Cross-Check): 遍历 的所有可能数值集合与 的所有可能数值集合,检查整除关系。

    • 条件:x % y == 0y % x == 0
    • 计算代价:Cost = (LenA - mapA[x]) + (LenB - mapB[y])
    • 维护全局最小值。

代码实现

#include <bits/stdc++.h>
#include <limits>
#include <unordered_map>
using namespace std;
using ll = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    string a, b;
    cin >> a >> b;

    auto generate = [](const string & str) -> unordered_map<int, int> {
        int len = str.length();
        unordered_map<int, int> dict;

        for (unsigned int mask = 1; mask < (1 << len); mask++) {
            string subValStr = "";
            for (int i = 0; i < len; i++) {
                if ((mask >> i) & 1) {
                    subValStr += str[i];
                }
            }

            ll subVal = stoll(subValStr);
            int curLen = subValStr.length();
            if (dict.count(subVal) == 0 || curLen > dict[subVal]) {
                dict[subVal] = curLen;
            }
        }

        return dict;
    };

    auto mapA = generate(a);
    auto mapB = generate(b);
    int minOps = numeric_limits<int>::max();

    for (auto [va, la] : mapA) {
        if (va == 0)
            continue;
        for (auto [vb, lb] : mapB) {
            if (vb == 0)
                continue;
            if (va % vb == 0 || vb % va == 0) {
                int curOps = a.length() - la + b.length() - lb;
                minOps = min(minOps, curOps);
            }
        }
    }

    if (minOps == numeric_limits<int>::max())
        minOps = -1;
    cout << minOps << endl;
}
#牛客新年AI问运#
每日一题@牛客网 文章被收录于专栏

牛客网每日一题

全部评论

相关推荐

01-08 11:19
已编辑
深圳职业技术学院 护士
我是从大一下学期5月开始转互联网的,原因很简单,对本专业的就业薪资与前景非常不满,而我特别想赚钱,所以选了互联网,而又因为带我的师兄都是前端,所以阴差阳错就做了前端当时的梦想就是进腾讯,进腾讯,进腾讯!大一下学期学了3个月的前端的基础知识后,开始参加学校工作室的考核,当时整个暑假都没回家,跑去自习室和考研的同学坐一下,那段时间我敢说我去的比大多数人早,走的比大多数人晚,把所有的时间精力都扑在做工作室考核上面,不过结果非常遗憾,我竞争不过两个超级大神,最后进不去了(广工的anyview是我一身之痛)不过进了物理学院的软件组,有了自己的工位还有好多转码师兄的指导后,开始长达半年的实验室之旅......在这半年,我几乎没有上课,没有去哪里玩,我像一个被写了程序的机器人一样,7点半起床,去实验室学前端,一直到晚上10点&nbsp;11点。我太笨了,太笨了,学东西太慢了,coderwhy的网课看了一遍又一遍,项目代码写了一遍又一遍,红宝书也是一遍一遍的看......就这样,过完了这打了鸡血的半年,寒假也只回去十天左右,然后就到了24年的3月我开始焦虑,非常非常的焦虑与害怕,因为我开始刷牛客了,开始去网上了解各种就业信息,一大堆负面信息朝我涌来,我不知道怎么区分就全盘接收前端已死,互联网完蛋了,非科班别想了,双非别想了,没有学历就等于判了死刑......有半个月我半夜都会被吓醒,后面想到的一个破局之路就是刷实习,大量的堆实习,弥补我双非的学历,非科班的专业带来的巨大劣势于是开始转战图书馆,找了考研的人一起坐,他们什么时候去我就什么时候去,开始背八股,前端三件套,框架,工程化,算法,计算机网络......这些对我当时的我来说太多了太多了,也太难太难了,越看越焦虑,越焦虑我越不敢停下来,每天晚上都要去跑5公里来让自己平静下来就这样过了一个多月,我准备的七七八八开始投实习了,第一次面试,我整个人紧张的止不住的颤抖,喝了一杯又一杯的水,上了一次又一次的厕所,皇天不负有心人,在四月底找到了自己的第一份外包实习,很大程度地缓解了我的焦虑,回去休息了半个月五一后入职,实习了一个星期左右,感觉太难受了,工作氛围及其压抑,同事也是感觉都乱来的,而且喜欢打压我,我在写算法的时候,他们老说不用写这个,这些是大厂才要的,你又进不去大厂......&nbsp;后面我只能偷偷跑楼下写,过了小半个月我实在呆不下去就离职回学校了,第一段实习就这样结束了,而且老板不给我发工资......于是我开始在学校二次沉淀了,开始大量刷leetcode&nbsp;代码随想录&nbsp;codetop&nbsp;准备更强的项目&nbsp;更深入地背八股,于是一直学啊学啊,那个暑假就回去两个星期学车,其他时间都呆在学校的实验室里24年8月开始全面投实习,拿了古茗&nbsp;卓望数码的offer,本来打算去杭州古茗的,结果美团打电话说面试通过,阴差阳错地去了上海美团,开启了自己的第一段实习刚去没多久,还没适应那里的生活工作环境,学校传来噩耗,外出实习被抓到了,老师逼我回去,说不回去毕不了业,我当时听完电话后,整个人崩溃了,我跑去公司楼道间一直哭,我不甘心,我太不甘心了,我不甘心来之不易的实习泡汤,幸好后面申请了一门实验课重修,如愿留在上海于是就在上海美团实习了四个月,一直到了25年1月,我开始飘了,我感觉自己牛逼坏了,感觉美团平台不够高,想去更高的腾讯和字节,放弃了美团核心部门,而且高转正率的机会,选择了离职,当时还在牛客写了一篇长文于是回家休息到年后,2月多开始回学校全力准备暑期实习,一直面一直挂,直到5月份才找到字节的实习,这三个月是我最痛苦最煎熬的日子,我的自信心被不断的击碎,一直面一直挂,而身边朋友开始接连上岸,我开始怀疑自己,开始后悔当时的决定,开始觉得自己就是一个看不清自己的傻逼然后呢,4月底&nbsp;在没招了,万念俱灰的时候,字节约面试了,一点也不想复习,裸面,结果阴差阳错给我干进去了5月中开始字节的实习,虽然压力比较大,但还可以接受,平平稳稳能干了三个月,自我感觉良好,以为转正稳了,结果到八月初的时候,通知转正失败,当时天都塌了,然后开始找其他部门的机会,后面活水成功,去另一个部门实习了一个月,其实转正概率也不小,但是当时也是心比天高,以为自己牛逼坏了,所以选择离职秋招9月中开始全面秋招,结果大家也知道,秋招大溃败,各种终面挂&nbsp;hr面挂&nbsp;排序挂&nbsp;有时候也不知道为什么挂,问题也都答出来了,算法也都写出来了,但就是挂哈哈哈哈其中很多时间都是在打字节的复活赛,反复仰卧起坐,反复鞭尸,后面感觉面字节跟回家和亲戚聊天一样,他会问什么我都知道,甚至我可以抢答,面完还能聊天开点玩笑......在12月中的时候,字节又约面了,阴差阳错又到了三面,结果还给整挂了,当时确实破防的要死,然后转部门面试,本来打算拒绝的,因为实在太心累,太折磨了,但还是咬咬牙去面了,然后莫名其妙问的也就那些,三面还整了几道脑筋急转弯,本来以为又要挂了,结果过了,据说是因为我的竞争对手三面ai作弊被发现了,所以只面了她16分钟,所以就轮到我了,我也不用hr面直接审批,然后审批半天,隔天直接谈薪,hr开了个我拒绝不了的薪资,而且表达出来的意思是无论其他开多少字节都能match的意思,诚意满满回望这两年多的经历,真的是非常非常感慨,我想和大家说的是每个人都会有属于自己花期,只是时间的问题而已,努力踏实做事,终究会有回报!我也曾在这条路上迷茫、焦虑、崩溃与无助,但我做的唯一的一件事情就是,整理好心情,重新出发,坚持下去,光脚的不怕穿鞋的,拼了兄弟们!
码农索隆:我感觉兄弟你所处在环境已经算是双非中比较好的了,双非院校中很少有实验室,也鲜有师哥师姐会带着去学习,而你也很争气抓住了这次机会,一飞冲天
现在前端的就业环境真的很...
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
昨天 17:04
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务