华为 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%能救活,适配各类控制器...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
前端高频面试题2:浏览器/计算机网络
本专栏相关链接 前端高频面试题1:HTML/CSS 前端高频面试题2:浏览器/计算机网络 前端高频面试题3:JavaScript 1.什么是强缓存、协商缓存? 强缓存: 当浏览器请求资源时,首先检查本地缓存是否命中。如果命…...
