【字节跳动高频面试题】不超过 N 的最大数拼接

题目描述

给定一个按 非递减顺序 排列的数字字符数组 digits(如 ["1","3","5","7"]),你可以任意次数使用这些字符,拼接成一个正整数

请返回:所有能拼出且 ≤ 给定整数 n 的正整数中,值最大的那个


示例

输入:digits = ["1","3","5","7"], n = 100
输出:77

解法一:暴力回溯(Backtrack 贪心)

思路概览

我们希望构造一个不大于 n 的数,且尽可能大。每一位从高位到低位逐位尝试:

  1. 若该位能找到一个 ≤ s[i] 的最大字符 d

    • 如果 d == s[i],继续匹配下一位;
    • 如果 d < s[i],则当前为转折点,后面全部填 digits 中最大值,直接构成答案;
  2. 如果该位没有合法字符(即所有字符都 > 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 原题推荐

LeetCode 902. 最大为 N 的数字组合

  • 类型:数位 DP
  • 难度:中等
  • 高频企业题:字节跳动、美团、阿里

总结

方法 思路 优点 缺点
回溯贪心法 模拟构造 逻辑直观,易于调试 实现较繁琐,回退处理需细致
数位 DP 状态转移+缓存 可扩展,适合复杂限制条件 学习门槛略高,状态较多

【字节跳动高频面试题】不超过 N 的最大数拼接的更多相关文章

  1. 字节跳动-前端面试题 Multi Promise Order

    字节跳动-前端面试题 Multi Promise Order Promise Order Async/Await async function async1 () { console.log('asy ...

  2. 双非本科字节跳动Android面试题分享(已拿offer)

    基本情况 本人系非985非211普通本科生一枚,有实习有项目经历但成绩普通,在面试前刷了很多面经.面试题,这里也把自己的分享下,做个回报好了,顺便攒攒人品,一到这种时候人就迷信起来了. 面试是以视频面 ...

  3. 字节跳动社会招聘&内推-帮助你更快加入字节跳动

    字节跳动社会招聘&内推「[内推码]:4J8CA3W」 内推时间:一直有效 招聘对象:根据招聘要求而定 社招投递链接: https://job.toutiao.com/s/de5teaA 应届生 ...

  4. 字节跳动Android实习面试难吗,应该如何应对?

    字节跳动的面试难不难其实很难去非常准确的定义,但是能肯定的一点是,字节跳动的面试题都很有水平,真正考察了该岗位在以后工作中需要的能力. 大学学的Java后面又自学Android方向,跟着老师在实验室做 ...

  5. 2019 字节跳动java面试笔试题 (含面试题解析)

      本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.字节跳动等公司offer,岗位是Java后端开发,因为发展原因最终选择去了字节跳动,入职一年时间了,也成为了面 ...

  6. 最新 字节跳动java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.字节跳动等10家互联网公司的校招Offer,因为某些自身原因最终选择了字节跳动.6.7月主要是做系统复习.项目复盘.Leet ...

  7. 多次面试被拒,‘宅家苦修’30天,终获美团offer(含字节跳动/阿里/腾讯等大厂面试题整理)

    背景:双非渣本. 今年由于疫情,上半年一直在家里.2月份本来无忧无虑,呆在家里不给国家添乱的时候,发现身边的同学找到了大厂的offer.心里开始有点慌张.本来想在3月份如果能回到学校,就开始考研之路, ...

  8. 从阿里、腾讯的面试真题中总结了这11个Redis高频面试题

    前言 现在大家的工作生活基本已经是回归正轨了,最近也是迎来了跳槽面试季,有些人已经拿到了一两个offer了. 这段时间收集了阿里.腾讯.百度.京东.美团.字节跳动等公司的Java面试题,总结了Redi ...

  9. 字节跳动实习面经分享(已拿offer附攻略)

    大家好,我是bigsai,今天给大家分享自己字节跳动面试经验分享. enum我面得岗位是后台实习开发,具体部门是懂车帝,总体感觉就是字节的流程真的好快,只要安排面试,那流程接着很快. 大概是上上周投递 ...

  10. 一份热乎的字节跳动客户端面经,已拿Offer

    字节面试过程: 4月4号进行内推,7天的简历评估,11号接到电话面试,尽管猝不及防回答仓促,但好在前期准备充分,通过.14号现场面试,次日收到通知,通过,二面.三面都很顺利.20号进行HR面,26号收 ...

随机推荐

  1. CM311-1A魔百和刷armbian或openwrt系统包

    系统包下载链接:Openwrt:阿里云盘链接:https://www.aliyundrive.com/s/tEemRbs1TYB已失效下载后请解压!!!!!!!!! Armbian:链接:https: ...

  2. 基于源码分析 HikariCP 常见参数的具体含义

    HikariCP 是目前风头最劲的 JDBC 连接池,号称性能最佳,SpringBoot 2.0 也将 HikariCP 作为默认的数据库连接池. 要想用好 HikariCP,理解常见参数的具体含义至 ...

  3. Asp.net mvc基础(六)TempData

    在客户端重定向或验证码等情况下,由于要跨请求的存取数据,是不能放到ViewBag.Model中,需要"暂时存到Session中,用完了删除"的需求:使用TempData可以做到. ...

  4. issue: java.lang.NoClassDefFoundError: javax/el/ELManager

    问题描述: Context initialization failed org.springframework.beans.factory.BeanCreationException: Error c ...

  5. 搞定 XLSX 预览?别瞎找了,这几个库(尤其最后一个)真香!

    -   Hey, 我是 沉浸式趣谈 -   本文首发于[沉浸式趣谈],我的个人博客 **https://yaolifeng.com** 也同步更新. -   转载请在文章开头注明出处和版权信息. - ...

  6. Python3批量爬取美女照片并保存到本地(二)

    Python3批量爬取美女照片并保存到本地(二) 上一波写错了,很尴尬,就能爬显示的一部分照片,网站有限制,从上波的爬取可以看出来,返回的json中只有一部分图片,其余的需要登录才能下载,我们这次通过 ...

  7. C语言函数指针解析

    C语言函数指针解析 一.函数指针的本质 函数指针是存储函数内存地址的变量,它允许程序在运行时动态调用不同的函数.与数据指针不同,函数指针指向的是可执行代码段. /* 典型声明方式 */ int (*f ...

  8. codeup之冒泡排序

    Description 从键盘上输入10个整数,用冒泡法对这10个数进行排序(由小到大). Input 以空格分隔的10个整数 Output 依次输出排好序的10个整数,每个数占一行. Sample ...

  9. stopPropagation()方法阻止父级事件

    方式一 <div id="div1"> <div id="div2"></div> </div> $(" ...

  10. 20244104 实验二《Python程序设计》实验报告

    课程:<Python程序设计> 班级: 2441 姓名: 陈思淼 学号:20244104 实验教师:王志强 实验日期:2025年4月5日 必修/选修: 公选课 1.实验内容 设计并完成一个 ...