华为 OD 一面算法原题
2.2 亿彩票公布调查结果
昨天,闹得沸沸扬扬的《10 万中 2.2 亿》的彩票事件,迎来了官方公告。

简单来说,调查结果就是:一切正常,合规合法。
关于福利彩票事件,之前的推文我们已经分析过。
甚至在后面出现《双色球 6.8 亿》事件时,还用类似的逻辑分析写了回答发到过某乎:

这次所谓调查通报,其实还是没有走出使用「公信力」来进行自证的圈子。
该说的都说过了,本次不再点评。
...
回归主线。
今天接着看「华为 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]
为何值:
-
由于每个字符串只能使用一次,转移需要满足 s
的第i
位为 ,s
的第j
位为 的前提条件,含义为ws[i]
已被使用,而ws[j]
未被使用 -
满足前提条件 ,代表 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 << n;
int[][] g = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
String a = ws[i], b = ws[j];
int l1 = a.length(), l2 = b.length(), len = Math.min(l1, l2);
for (int k = len; k >= 1; k--) {
if (a.substring(l1 - k).equals(b.substring(0, k))) {
g[i][j] = k;
break;
}
}
}
}
int[][] f = new int[mask][n], p = new int[mask][n];
for (int s = 0; s < mask; s++) {
for (int i = 0; i < n; i++) {
if (((s >> i) & 1) == 0) continue;
for (int j = 0; j < n; j++) {
if (((s >> j) & 1) == 1) continue;
if (f[s | (1 << j)][j] <= f[s][i] + g[i][j]) {
f[s | (1 << j)][j] = f[s][i] + g[i][j];
p[s | (1 << j)][j] = i;
}
}
}
}
int max = f[mask - 1][0], idx = 0, last = -1, status = mask - 1;
for (int i = 1; i < n; i++) {
if (max < f[mask - 1][i]) {
max = f[mask - 1][i];
idx = i;
}
}
String ans = "";
while (status != 0) {
if (last == -1) ans = ws[idx];
else ans = ws[idx].substring(0, ws[idx].length() - g[idx][last]) + ans;
last = idx;
idx = p[status][idx];
status ^= (1 << last);
}
return ans;
}
}
Python 代码:
class Solution:
def shortestSuperstring(self, ws: List[str]) -> str:
n, mask = len(ws), 1 << len(ws)
g = [[0 for _ in range(n)] for _ in range(n)]
for i in range(n):
for j in range(n):
a, b = ws[i], ws[j]
l1, l2 = len(a), len(b)
length = min(l1, l2)
for k in range(length, 0, -1):
if a[l1 - k:] == b[:k]:
g[i][j] = k
break
f = [[0 for _ in range(n)] for _ in range(mask)]
p = [[0 for _ in range(n)] for _ in range(mask)]
for s in range(mask):
for i in range(n):
if (s >> i) & 1 == 0:
continue
for j in range(n):
if (s >> j) & 1 == 1:
continue
if f[s | (1 << j)][j] <= f[s][i] + g[i][j]:
f[s | (1 << j)][j] = f[s][i] + g[i][j]
p[s | (1 << j)][j] = i
max_val = f[mask - 1][0]
idx, last, status = 0, -1, mask - 1
for i in range(1, n):
if max_val < f[mask - 1][i]:
max_val = f[mask - 1][i]
idx = i
ans = ""
while status != 0:
if last == -1:
ans = ws[idx]
else:
ans = ws[idx][:len(ws[idx]) - g[idx][last]] + ans
last = idx
idx = p[status][idx]
status ^= 1 << last
return ans
C++ 代码:
class Solution {
public:
string shortestSuperstring(vector<string>& ws) {
int n = ws.size(), mask = 1 << n;
vector<vector<int>> g(n, vector<int>(n, 0));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
string a = ws[i], b = ws[j];
int l1 = a.length(), l2 = b.length(), len = min(l1, l2);
for (int k = len; k >= 1; k--) {
if (a.substr(l1 - k) == b.substr(0, k)) {
g[i][j] = k;
break;
}
}
}
}
vector<vector<int>> f(mask, vector<int>(n, 0)), p(mask, vector<int>(n, 0));
for (int s = 0; s < mask; s++) {
for (int i = 0; i < n; i++) {
if (((s >> i) & 1) == 0) continue;
for (int j = 0; j < n; j++) {
if (((s >> j) & 1) == 1) continue;
if (f[s | (1 << j)][j] <= f[s][i] + g[i][j]) {
f[s | (1 << j)][j] = f[s][i] + g[i][j];
p[s | (1 << j)][j] = i;
}
}
}
}
int max = f[mask - 1][0], idx = 0, last = -1, status = mask - 1;
for (int i = 1; i < n; i++) {
if (max < f[mask - 1][i]) {
max = f[mask - 1][i];
idx = i;
}
}
string ans = "";
while (status != 0) {
if (last == -1) ans = ws[idx];
else ans = ws[idx].substr(0, ws[idx].length() - g[idx][last]) + ans;
last = idx;
idx = p[status][idx];
status ^= (1 << last);
}
return ans;
}
};
TypeScript 代码:
function shortestSuperstring(ws: string[]): string {
const n = ws.length, mask = 1 << n;
const g = new Array(n).fill(0).map(() => new Array(n).fill(0));
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
const a = ws[i], b = ws[j];
const l1 = a.length, l2 = b.length;
const len = Math.min(l1, l2);
for (let k = len; k >= 1; k--) {
if (a.substring(l1 - k) === b.substring(0, k)) {
g[i][j] = k;
break;
}
}
}
}
const f = new Array(mask).fill(0).map(() => new Array(n).fill(0));
const p = new Array(mask).fill(0).map(() => new Array(n).fill(0));
for (let s = 0; s < mask; s++) {
for (let i = 0; i < n; i++) {
if (((s >> i) & 1) === 0) continue;
for (let j = 0; j < n; j++) {
if (((s >> j) & 1) === 1) continue;
if (f[s | (1 << j)][j] <= f[s][i] + g[i][j]) {
f[s | (1 << j)][j] = f[s][i] + g[i][j];
p[s | (1 << j)][j] = i;
}
}
}
}
let max = f[mask - 1][0], idx = 0, last = -1, status = mask - 1;
for (let i = 1; i < n; i++) {
if (max < f[mask - 1][i]) {
max = f[mask - 1][i];
idx = i;
}
}
let ans = "";
while (status != 0) {
if (last === -1) ans = ws[idx];
else ans = ws[idx].substring(0, ws[idx].length - g[idx][last]) + ans;
last = idx;
idx = p[status][idx];
status ^= (1 << last);
}
return ans;
}
-
时间复杂度:将字符串 的最大长度记为 ,预处理复杂度为 ;状态数量为 , DP
复杂度为 。构造答案复杂度为 。整体复杂度为 -
空间复杂度:
我是宫水三叶,每天都会分享算法知识,并和大家聊聊近期的所见所闻。
欢迎关注,明天见。
更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地 🎉🎉
相关文章:

华为 OD 一面算法原题
2.2 亿彩票公布调查结果 昨天,闹得沸沸扬扬的《10 万中 2.2 亿》的彩票事件,迎来了官方公告。 简单来说,调查结果就是:一切正常,合规合法。 关于福利彩票事件,之前的推文我们已经分析过。 甚至在后面出现《…...

FPGA-学会使用vivado中的存储器资源ROM(IP核)
问题: 某芯片,有500个寄存器,需要在上电的时候由FPGA向这些寄存器中写入初始值,初始值已经通过相应的文档给出了具体值,这些值都是已知的。 分析关键点: 数据量比较多(Verilog代码,通过case语句、always语句这种查找表的方式,数…...

自测-1 打印沙漏
文章预览: 题目算法代码 题目 算法 以前做过这个,那次是c语言写的,一点一点处理一层一层完成,这次我换了一种语言用了另一种思想使用递归去写,还是我们要先求出应该有多少层这个很容易,中间输出部分我们算…...
高级语言期末2009级B卷(计算机学院)
1.编写一个名为mystrcpy的函数,实现将字符串str1的偶数位子的字符的拷贝到另一个字符串str2中。并编写主函数,在主函数中从键盘读入一个长度<100的字符串str1,然后调用函数mystrcpy;最后输出str2,例如,读…...
c# using 用法
using命令空间 导入命名空间中的所有类型 如:using System.Text; using别名 using别名包括详细命名空间信息的具体类型,这种做法有个好处就是当同一个cs引用了两个不同的命名空间,但两个命名空间都包括了一个相同名字的类型的时候。当需要…...

【Django】执行查询—跨关系查询中的跨多值关联问题
跨多值查询 跨越 ManyToManyField 或反查 ForeignKey (例如从 Blog 到 Entry )时,对多个属性进行过滤会产生这样的问题:是否要求每个属性都在同一个相关对象中重合。 filter() 先看filter(),通过一个例子看…...

Spring八股 常见面试题
什么是Spring Bean 简单来说,Bean 代指的就是那些被 IoC 容器所管理的对象。我们需要告诉 IoC 容器帮助我们管理哪些对象,这个是通过配置元数据来定义的。配置元数据可以是 XML 文件、注解或者 Java 配置类。 将一个类声明为 Bean 的注解有哪些? Com…...

今年面试潮,说实话这个开发岗能不能冲?
自打华为 2019 年发布鸿蒙操作系统以来,网上各种声音百家争鸣。尤其是 2023 年发布会公布的鸿蒙 4.0 宣称不再支持 Android,更激烈的讨论随之而来。 当下移动端两大巨头瓜分了绝大部分市场: iOS 是闭源的,只有唯一的一家厂商&am…...

【前端素材】推荐优质在线花卉商城电商网页Flowery平台模板(附源码)
一、需求分析 1、系统定义 在线花卉商城是一个通过互联网提供花卉销售服务的电子商务平台,用户可以在该平台上浏览、选择和购买各种花卉产品。 2、功能需求 在线花卉商城是一个通过互联网提供花卉销售服务的电子商务平台,用户可以在该平台上浏览、选…...

★【递归】【构造二叉树】Leetcode 106.从中序与后序遍历序列构造二叉树
★【递归前序】【构造二叉树】Leetcode 106.从中序与后序遍历序列构造二叉树 105. 从前序与中序遍历序列构造二叉树 106.从中序与后序遍历序列构造二叉树:star:思路分析递归解法 105. 从前序与中序遍历序列构造二叉树递归解法 凡是构造二叉树>>>>>>>>&…...
linux检测和重启python脚本
#!/bin/bash# 检测Flask应用是否挂了 if ! pgrep -f "flask_app.py" >/dev/null; then# 重启Flask应用cd /path/to/your/flask/appnohup python3 flask_app.py >/dev/null 2>&1 & fi这是一个简单的bash脚本,用于检测Flask应用是否挂掉&a…...

HTML+CSS+JS:花瓣登录组件
效果演示 实现了一个具有动态花朵背景和简洁登录框的登录页面效果。 Code <section><img src"./img/background.jpeg" class"background"><div class"login"><h2>Sign In</h2><div class"inputBox"…...

Unity中URP下实现水体(水面反射)
文章目录 前言一、原理1、法一:使用立方体纹理 CubeMap,作为反射纹理使用2、法二:使用反射探针生成环境反射图,所谓反射的采样纹理 二、实现水面反射1、定义和申明CubeMap2、反射向量需要什么3、计算 N ⃗ \vec{N} N 4、计算 V ⃗…...
基于FastJson实现Json数据文件导入导出解析
哈喽,大家好,我是灰小猿,一个超会写bug的程序猿! 今天来记录一个在项目实战中比较实用的方法,主要是针对一些需要存在简单数据文件导入导出的场景,如:数据文件的简单备份、软件升版前后配置导入…...

JVM内存分配与垃圾收集流程
3.8 实战:内存分配与回收策略 3.8.1 对象优先在Eden分配 大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC。 3.8.2 大对象直接进入老年代 HotSpot虚拟机提供了-XX:Prete…...
【python】yaml转成json
姊妹篇:【python】json转成成yaml yaml数据: address:city: 北京市postalCode: 100000street: 北京路123号 age: 30 cart: - product:name: 笔记本电脑price: 1199.99quantity: 2 - product:name: 智能手机price: 599.99quantity: 1 children: - age: …...

css5定位
css 一.定位1.概念(定位定位模式边位移)2.静态位移static(不常用)3.相对定位relative(不脱标)(占位置)4.绝对定位absolute(脱标)(不占位置&#x…...
【解决】修改 UI界面渲染层级 的常见误区
开发平台:Unity 2021版本 问题描述 Unity 中管理 UI 上显示元素的前后层级关系大致为以下两种方式: 方式一:修改UI元素队列顺序与层级方式二:使用 Canvas 组件中的 Override Sort 属性配置 方式二 对应复杂的 UI 层级关系将常…...

蓝桥杯练习系统(算法训练)ALGO-995 24点
资源限制 内存限制:256.0MB C/C时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s 问题描述 24点游戏是一个非常有意思的游戏,很流行,玩法很简单:给你4张牌,每张牌上有数…...
汽车电子笔记:BootLoader升级过程疑难问题解决方式(Bootloader响应10 02 + 刷死拯救机制)
目录 1、概述 2、如何在BootLoader响应10 02 2.1、实现流程图 2.2、实现方式(代码思路) 3、刷死拯救机制(100%能救活,适配各类控制器...

IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...