【字节跳动高频面试题】不超过 N 的最大数拼接
【字节跳动高频面试题】不超过 N 的最大数拼接
题目描述
给定一个按 非递减顺序 排列的数字字符数组 digits
(如 ["1","3","5","7"]
),你可以任意次数使用这些字符,拼接成一个正整数。
请返回:所有能拼出且 ≤ 给定整数 n
的正整数中,值最大的那个。
示例
输入:digits = ["1","3","5","7"], n = 100
输出:77
解法一:暴力回溯(Backtrack 贪心)
思路概览
我们希望构造一个不大于 n
的数,且尽可能大。每一位从高位到低位逐位尝试:
若该位能找到一个
≤ s[i]
的最大字符d
:- 如果
d == s[i]
,继续匹配下一位; - 如果
d < s[i]
,则当前为转折点,后面全部填digits
中最大值,直接构成答案;
- 如果
如果该位没有合法字符(即所有字符都 >
s[i]
),则需要回退(Backtrack):- 回退到前一位,寻找一个更小字符,之后所有位都填最大字符。
若所有位都成功对齐 n
的每一位字符,则答案为 n
本身。否则返回构造出的最大值。
时间复杂度分析
最坏情况每一位都需要回退多次;
时间复杂度约为
O(L × |digits|)
,其中:L = log10(n) + 1
为位数;|digits| ≤ 9
。
即便 n
非常大(如 10^18
),依然能在毫秒级别内完成。
C++ 实现
int bytedance1(vector<string>& digits, int n) {
bool flag = false; // 是否已经满足 <,之后可以直接填最大digit
string s = to_string(n);
n = s.size();
unordered_map<char, int> mp;
for(int i = 0; i < digits.size(); i++) mp[digits[i][0]] = i + 1;
vector<char> res(n, digits[0][0]);
for(int i = 0; i < n && !flag; i++) {
for(auto& d : digits) {
if(d[0] <= s[i]) res[i] = d[0];
}
if(res[i] < s[i]) {
flag = true;
for(int j = i + 1; j < n; j++) res[j] = digits.back()[0];
} else if(res[i] > s[i]) { // 无法继续匹配
int j = i;
while(j >= 0 && res[j] == digits[0][0]) j--;
if(j == -1) {
res.resize(n - 1, digits.back()[0]);
} else {
for(auto& d : digits) {
if(d[0] < s[j]) res[j] = d[0];
}
j++;
for(; j < n; j++) res[j] = digits.back()[0];
}
flag = true;
}
}
for(auto& ch : res) cout << ch;
cout << endl;
return 0;
}
解法二:数位 DP(Digit DP)
解题框架
使用数位 DP 框架模板,通过参数限制合法性。
L
:下界,补齐成和R
同样的位数(例如"001"
);R
:上界,即n
;digits
:枚举所有合法的数字;状态参数:
i
:当前位;isZero
:是否还处于前导零;isLow
:当前是否仍受下界限制;isHigh
:当前是否仍受上界限制。
关键转移逻辑
int dfs(int i, int isZero, int isLow, int isHigh);
- 当
isZero && l == 0
时,可以跳过当前位; - 当
!isZero && !isLow && !isHigh
时,结果可以记忆化缓存; - 尝试填入所有合法的
digits
中的数字,满足边界限制即可。
C++ 实现
string L, R;
vector<int> digits;
int n, f[10];
string tmp = "", res = "";
int dfs(int i, int isZero, int isLow, int isHigh) {
if(i == n) {
if(res == "") res = tmp; // 保存最大值
return !isZero;
}
if(!isZero && !isLow && !isHigh && ~f[i]) return f[i];
int l = isLow ? L[i] - '0' : 0;
int r = isHigh ? R[i] - '0' : 9;
int ans = 0;
for(int& d : digits) {
if(d >= l && d <= r) {
tmp.push_back(d + '0');
ans += dfs(i + 1, 0, isLow && d == l, isHigh && d == r);
tmp.pop_back();
}
}
if(isZero && l == 0) ans += dfs(i + 1, 1, 1, isHigh && r == 0);
if(!isZero && !isLow && !isHigh) f[i] = ans;
return ans;
}
int bytedance2(vector<string>& digitsStr, int n) {
R = to_string(n);
L = string(R.size() - 1, '0') + "1";
::n = R.size();
digits.clear();
for(auto& x : digitsStr) digits.emplace_back(x[0] - '0');
ranges::reverse(digits); // 从大到小尝试
memset(f, -1, sizeof f);
dfs(0, 1, 1, 1);
cout << res << endl;
return 0;
}
LeetCode 原题推荐
- 类型:数位 DP
- 难度:中等
- 高频企业题:字节跳动、美团、阿里
总结
方法 | 思路 | 优点 | 缺点 |
---|---|---|---|
回溯贪心法 | 模拟构造 | 逻辑直观,易于调试 | 实现较繁琐,回退处理需细致 |
数位 DP | 状态转移+缓存 | 可扩展,适合复杂限制条件 | 学习门槛略高,状态较多 |
【字节跳动高频面试题】不超过 N 的最大数拼接的更多相关文章
- 字节跳动-前端面试题 Multi Promise Order
字节跳动-前端面试题 Multi Promise Order Promise Order Async/Await async function async1 () { console.log('asy ...
- 双非本科字节跳动Android面试题分享(已拿offer)
基本情况 本人系非985非211普通本科生一枚,有实习有项目经历但成绩普通,在面试前刷了很多面经.面试题,这里也把自己的分享下,做个回报好了,顺便攒攒人品,一到这种时候人就迷信起来了. 面试是以视频面 ...
- 字节跳动社会招聘&内推-帮助你更快加入字节跳动
字节跳动社会招聘&内推「[内推码]:4J8CA3W」 内推时间:一直有效 招聘对象:根据招聘要求而定 社招投递链接: https://job.toutiao.com/s/de5teaA 应届生 ...
- 字节跳动Android实习面试难吗,应该如何应对?
字节跳动的面试难不难其实很难去非常准确的定义,但是能肯定的一点是,字节跳动的面试题都很有水平,真正考察了该岗位在以后工作中需要的能力. 大学学的Java后面又自学Android方向,跟着老师在实验室做 ...
- 2019 字节跳动java面试笔试题 (含面试题解析)
本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.字节跳动等公司offer,岗位是Java后端开发,因为发展原因最终选择去了字节跳动,入职一年时间了,也成为了面 ...
- 最新 字节跳动java校招面经 (含整理过的面试题大全)
从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.字节跳动等10家互联网公司的校招Offer,因为某些自身原因最终选择了字节跳动.6.7月主要是做系统复习.项目复盘.Leet ...
- 多次面试被拒,‘宅家苦修’30天,终获美团offer(含字节跳动/阿里/腾讯等大厂面试题整理)
背景:双非渣本. 今年由于疫情,上半年一直在家里.2月份本来无忧无虑,呆在家里不给国家添乱的时候,发现身边的同学找到了大厂的offer.心里开始有点慌张.本来想在3月份如果能回到学校,就开始考研之路, ...
- 从阿里、腾讯的面试真题中总结了这11个Redis高频面试题
前言 现在大家的工作生活基本已经是回归正轨了,最近也是迎来了跳槽面试季,有些人已经拿到了一两个offer了. 这段时间收集了阿里.腾讯.百度.京东.美团.字节跳动等公司的Java面试题,总结了Redi ...
- 字节跳动实习面经分享(已拿offer附攻略)
大家好,我是bigsai,今天给大家分享自己字节跳动面试经验分享. enum我面得岗位是后台实习开发,具体部门是懂车帝,总体感觉就是字节的流程真的好快,只要安排面试,那流程接着很快. 大概是上上周投递 ...
- 一份热乎的字节跳动客户端面经,已拿Offer
字节面试过程: 4月4号进行内推,7天的简历评估,11号接到电话面试,尽管猝不及防回答仓促,但好在前期准备充分,通过.14号现场面试,次日收到通知,通过,二面.三面都很顺利.20号进行HR面,26号收 ...
随机推荐
- unigui的demo-\Demos\Desktop\DBAppDemo\SimpleDemo.dproj【11】
这个demo很简单. 一个客户表,还有一个票据主从表. 看程序界面: 包括数据提交,彻头彻尾的c/s程序.你完全按照传统的C/S程序模式做开发就可.好处是效率.效率.还是效率! 你还有什么不满意!如果 ...
- Golang高性能引擎:ZKmall开源商城支撑百万级日活交易流畅运行
在电商业务高并发.低延迟的严苛场景下,技术栈的选择直接决定系统上限.ZKmall开源商城基于Golang技术生态,以协程级并发.毫秒级响应为核心优势,为百万级日活电商平台提供高性能解决方案.本文从架构 ...
- C#之值类型与引用类型--out参数--ref参数-"=="、Equals和ReferenceEquals之间的区别
一.值类型和引用类型 1.值类型 (1)值类型的大小是固定的 (2)值类型都派生自ValueType (3)值类型不能继承,只能实现接口 2.值类型:int.char.double.float.lon ...
- 康谋分享 | 数据隐私和匿名化:PIPL与GDPR下,如何确保数据合规?(二)
在上期数据隐私和匿名化系列文章中,我们主要分享了<中国个人信息保护法>(PIPL)和<欧盟通用数据保护条例>(GDPR)在涵盖范围.定义.敏感信息等方面的异同点,今天,我们将重 ...
- DPDI(Dispatch PDI)kettle调度管理平台介绍
DPDI online产品简介 DPDI Online 是一款基于Kettle的强大在线任务调度平台,凭借其高效与灵活性,专为调度和监控Kettle客户端生成的ETL任务而设计 DPDI Online ...
- 如何0基础学stm32?
如何0基础学stm32? 作为一个混迹嵌入式领域十余年的老兵,每次看到"0基础学STM32"这样的提问,我都忍不住想笑,又有些无奈.这就像问"如何0基础学开飞机" ...
- 解决Ubuntu 20.04升级后gnome-control-center设置程序无法打开问题
解决Ubuntu 20.04升级后gnome-control-center设置程序无法打开问题 Ubuntu 20.04 系统升级后,发现gnome设置程序无法正常打开了. 在终端运行命令查看错误信息 ...
- Spring基于注解的AOP事务控制
Spring基于注解的AOP事务控制 源码 代码测试 pom.xml <?xml version="1.0" encoding="UTF-8"?> ...
- Redis 连接池耗尽的一次异常定位
转载请注明出处: 最近在项目中遇到一个奇怪的现象,项目运行环境中的redis在业务运行中,一直没有更新redis的值,在服务的日志中也没有看到相关的异常,导致服务看起来正常,但和redis相关的功能却 ...
- k8s入门操作
kubectl -->apiserver 管理工具 管理k8s集群 增删改查node kubectl get service/node/replicaset/deployment/statefu ...