华为 OD 一面算法原题

慈云数据 1年前 (2024-03-15) 技术支持 63 0

2.2 亿彩票公布调查结果

昨天,闹得沸沸扬扬的《10 万中 2.2 亿》的彩票事件,迎来了官方公告。

alt

简单来说,调查结果就是:一切正常,合规合法

关于福利彩票事件,之前的推文我们已经分析过。

甚至在后面出现《双色球 6.8 亿》事件时,还用类似的逻辑分析写了回答发到过某乎:

alt

这次所谓调查通报,其实还是没有走出使用「公信力」来进行自证的圈子。

该说的都说过了,本次不再点评。

...

回归主线

今天接着看「华为 OD」一面算法原题。

昨天分享了一道「子序列」相关的「华为 OD」一面算法原题,很多网友表示不可思议。

那道题在 LeetCode 中是 Hard,现在连 OD 都这么卷了吗?

是的,OD 都开始卷了。

这其实不难理解。

算法在笔试面试中出现,主要是起到一个「过滤」的作用

以前面试算法题难度普遍没有很高,是因为出到普通难度,也足以产生过滤作用,再难可能就没有候选人做出来,反而起不到过滤效果。

现如今,随着互联网大厂的各种裁员,加上应届大学生毕业人数屡创新高,连华为 OD 岗位都供远大于求了,因此算法题难度也上来了。

题目描述

平台:LeetCode

题号:943

给定一个字符串数组 words,找到以 words 中每个字符串作为子字符串的最短字符串。

如果有多个有效最短字符串满足题目条件,返回其中任意一个即可。

我们可以假设 words 中没有字符串是 words 中另一个字符串的子字符串。

示例 1:

输入:words = ["alex","loves","leetcode"]

输出:"alexlovesleetcode"

解释:"alex","loves","leetcode" 的所有排列都会被接受。

示例 2:

输入:words = ["catg","ctaagt","gcta","ttca","atgcatc"]

输出:"gctaagttcatgcatc"

提示:

  • words[i] 由小写英文字母组成
  • words 中的所有字符串互不相同

    状压 DP

    为了方便,将 words 记为 ws。

    预处理二维数组 g 来表示字符串 ws[i] 和 ws[j] 的重叠部分的长度:若 g[i][j] = len 代表字符串 ws[i] 长度为 len 的后缀与字符串 ws[j] 长度为 len 的前缀相同。

    另外用一个二进制数 status 来代表当前超级串 ans 对 ws 的使用(覆盖)情况:若 status 的第 i 位为 1 代表字符串 ws[i] 已被使用(即 ws[i] 已是 ans 的子串),若 status 的第 i 位为 0 代表 ws[i] 未被使用

    我们知道,当所有的 时,代表所有拼接方式长度均为 ,即不能通过产生重叠部分来缩短超级串的长度。

    因此,最小化超级串 ans 的长度等价于最大化重叠部分的长度

    定义 代表当前状态为 s 且当前最后一个使用到的字符串为 ws[i] (当前超级串 ans 的结尾部分为 ws[i])时的最大重合长度。

    最终超级串的长度为所有字符串的总长度 减去最大重合长度 。

    不失一般性考虑 可用于更新哪些状态,我们可枚举接在字符串 ws[i] 后面的字符串 ws[j] 为何值:

    1. 由于每个字符串只能使用一次,转移需要满足 s 的第 i 位为 , s 的第 j 位为 的前提条件,含义为 ws[i] 已被使用,而 ws[j] 未被使用
    2. 满足前提条件 ,代表 ws[j] 可接在 ws[i] 后面,此时有状态转移方程:

    接下来,考虑如何构建具体方案。

    使用二维数组 记录每个状态是由哪个前驱转移而来:若有 ,代表取得最大重叠长度过程中,字符串 ws[j] 接在 ws[i] 后面。

    我们从后往前对 ans 进行构造,若 ans = ws[0] + ws[1] + ... + ws[k - 1] + ws[k],我们是先找 ws[k],再通过 ws[k] 找 ws[k - 1],直到将整个 ans 构建出来。

    构造过程中使用变量解释如下:

    • ans 为具体的超级串
    • status 代表当前还有哪些字符串待拼接到,初始化为 ,代表还没有任何字符串拼接到 ans 中
    • idx 代表当前处理到的字符串下标,初始化通过遍历所有的 找到合适的 作为 idx
    • last 代表前一个处理到字符串下标,初始化为 -1

      一些细节:当 last 不为初始值 -1 时,需要跳过 ws[idx] 与 ws[last] 的重复部分进行拼接。

      Java 代码:

      class Solution {
          public String shortestSuperstring(String[] ws) {
              int n = ws.length, mask = 1 
微信扫一扫加客服

微信扫一扫加客服