【秋招笔试】09.19华子(海外留学生版)秋招-三语言题解
🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试
💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 大厂实习经历
✨ 本系列打算持续跟新
春秋招笔试题
👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸
✨ 笔试合集传送们 -> 🧷春秋招笔试合集
🍒 本专栏已收集
120+
套笔试题,笔试真题
会在第一时间跟新🍄 题面描述等均已改编,如果和你笔试题看到的题面描述不一样请理解,做法和题目本质基本不变。
🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力 💞
🌈 华为秋招(海外留学生版)笔试,来啦!!!
🍥 留学生的题目难度相对于国内来说总体来看会简单一丢丢,但整体题目风格,难度,几乎都是一样的哦~
tips
国内的有些题会复用留学生考过的题目哦,国内机考的朋友可以把留学生的题目也刷一刷1️⃣ 推公式/枚举/二分,这题的做法很多,由于数据比较小,大家怎么做都可以哈
2️⃣ 模拟题,华子最喜欢的阅读理解+模拟,建议大家多练!!!
3️⃣ 力扣原题改编,今年秋招华为出了很多这种力扣的改编题,基本二三两题都是有出处的,大家平时没事可以多刷刷扣子,打打牛客/力扣的周赛。
💎 01.珠宝商的难题 评测链接🔗
问题描述
K小姐是一位著名的珠宝商,她最近收到了一批特殊的宝石。每颗宝石都有一个独特的"光泽值",这个值是由宝石的十六进制编码中各位数字之和决定的(0-9代表0-9,A:10、B:11、C:12、D:13、E:14、F:15)。
K小姐想要将这些宝石按照特定的顺序排列,她需要知道每颗宝石右侧第一个光泽值更高的宝石的位置。如果一颗宝石右侧没有光泽值更高的宝石,则记为-1。
请你帮助K小姐设计一个程序,来解决这个排列问题。
输入格式
第一行包含一个正整数 ,表示宝石的数量。
第二行包含 个由空格分隔的非负整数,表示每颗宝石的编码。
输出格式
一行,包含 个整数,表示每颗宝石右侧第一个光泽值更高的宝石的位置(索引从0开始),如果不存在则输出-1。
样例输入1
3
12 3 24
样例输出1
-1 2 -1
样例输入2
5
15 8 23 42 7
样例输出2
-1 3 3 -1 -1
样例解释
样例1 | 十六进制表示分别为:[C, 3, 18] 对应的光泽值分别为:[12, 3, 1+8=9] - 第一颗宝石(12,光泽值12)右侧没有更高光泽值的宝石,返回-1 - 第二颗宝石(3,光泽值3)右侧第一个更高光泽值的宝石是24(光泽值9),位于索引2 - 第三颗宝石(24,光泽值9)右侧没有更高光泽值的宝石,返回-1 |
样例2 | 十六进制表示分别为:[F, 8, 17, 2A, 7] 对应的光泽值分别为:[15, 8, 8, 2+10=12, 7] - 第一颗宝石(15,光泽值15)右侧没有更高光泽值的宝石,返回-1 - 第二颗宝石(8,光泽值8)和第三颗宝石(23,光泽值8)右侧第一个更高光泽值的宝石是42(光泽值12),位于索引3 - 第四颗宝石(42,光泽值12)和第五颗宝石(7,光泽值7)右侧没有更高光泽值的宝石,返回-1 |
数据范围
题解
单调栈
本质是找出数组中每个元素右侧第一个更大元素的位置,这个可以用单调栈来解决,但是需要先将原始的宝石编码转换为"光泽值"。
从右向左遍历数组,维护一个单调递减的栈,具体步骤如下:
- 首先,将所有宝石编码转换为光泽值。
- 从右向左遍历光泽值数组。
- 对于每个元素,while循环比较栈顶元素:
- 如果当前元素的光泽值大于栈顶元素的光泽值,就将栈顶元素弹出。
- 重复这个过程,直到栈为空或者栈顶元素的光泽值大于当前元素。
- 如果栈不为空,栈顶元素就是当前元素右侧第一个光泽值更大的元素。
- 将当前元素的索引压入栈中。
这个算法的时间复杂度是 ,因为每个元素最多入栈和出栈一次。空间复杂度也是 ,用于存储结果数组和栈。
参考代码
- Python
def calculate_gloss(n):
"""计算宝石的光泽值"""
gloss = 0
while n > 0:
gloss += n % 16
n //= 16
return gloss
def find_next_greater(gems):
n = len(gems)
gloss_values = [calculate_gloss(gem) for gem in gems]
result = [-1] * n
stack = []
# 从右向左遍历
for i in range(n - 1, -1, -1):
# 当栈不为空且当前元素的光泽值大于栈顶元素的光泽值时
while stack and gloss_values[i] >= gloss_values[stack[-1]]:
stack.pop()
# 如果栈不为空,栈顶元素就是右侧第一个光泽值更大的宝石
if stack:
result[i] = stack[-1]
# 将当前索引入栈
stack.append(i)
return result
# 读取输入
n = int(input())
gems = list(map(int, input().split()))
# 计算结果并输出
result = find_next_greater(gems)
print(*result)
- Java
import java.util.*;
public class Main {
// 计算宝石的光泽值
private static int calculateGloss(long n) {
int gloss = 0;
while (n > 0) {
gloss += (int)(n % 16);
n /= 16;
}
return gloss;
}
// 找出每个宝石右侧第一个光泽值更高的宝石位置
private static int[] findNextGreater(long[] gems) {
int n = gems.length;
int[] glossValues = new int[n];
for (int i = 0; i < n; i++) {
glossValues[i] = calculateGloss(gems[i]);
}
int[] result = new int[n];
Arrays.fill(result, -1);
Stack<Integer> stack = new Stack<>();
// 从右向左遍历
for (int i = n - 1; i >= 0; i--) {
// 当栈不为空且当前元素的光泽值大于等于栈顶元素的光泽值时
while (!stack.isEmpty() && glossValues[i] >= glossValues[stack.peek()]) {
stack.pop();
}
// 如果栈不为空,栈顶元素就是右侧第一个光泽值更大的宝石
if (!stack.isEmpty()) {
result[i] = stack.peek();
}
// 将当前索引入栈
stack.push(i);
}
return result;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
long[] gems = new long[n];
for (int i = 0; i < n; i++) {
gems[i] = scanner.nextLong();
}
int[] result = findNextGreater(gems);
for (int i = 0; i < n; i++) {
System.out.print(result[i] + (i == n - 1 ? "" : " "));
}
}
}
- Cpp
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
#define int long long
// 计算宝石的光泽值
int calculateGloss(int n) {
int gloss = 0;
while (n > 0) {
gloss += n % 16;
n /= 16;
}
return gloss;
}
// 找出每个宝石右侧第一个光泽值更高的宝石位置
vector<int> findNextGreater(const vector<int>& gems) {
int n = gems.size();
vector<int> glossValues(n);
for (int i = 0; i < n; i++) {
glossValues[i] = calculateGloss(gems[i]);
}
vector<int> result(n, -1);
stack<int> s;
// 从右向左遍历
for (int i = n - 1; i >= 0; i--) {
// 当栈不为空且当前元素的光泽值大于等于栈顶元素的光泽值时
while (!s.empty() && glossValues[i] >= glossValues[s.top()]) {
s.pop();
}
// 如果栈不为空,栈顶元素就是右侧第一个光泽值更大的宝石
if (!s.empty()) {
result[i] = s.top();
}
// 将当前索引入栈
s.push(i);
}
return result;
}
signed main() {
int n;
cin >> n;
vector<int> gems(n);
for (int i = 0; i < n; i++) {
cin >> gems[i];
}
vector<int> result = findNextGreater(gems);
for (int i = 0; i < n; i++) {
cout << result[i] << (i == n - 1 ? "" : " ");
}
return 0;
}
🤖 02.智能仓库机器人 评测链接🔗
问题描述
在未来的智能仓库中,LYA公司开发了一款先进的机器人用于管理货架。仓库由一排排货架组成,每个货架有多层,每层可以放置一个货物。货物从底层开始摆放,每个货架的货物数量是随机的,但至少有一个。
这款机器人有两种检查模式:
- 横向检查:可以同时检查多个货架的同一层,耗时1分钟。
- 纵向检查:只能检查单个货架的所有层,耗时2分钟。
检查规则:
- 允许重复检查同一货物,但每次检查必须是连续的一段货架或货层。
- 单个货物的检查默认使用纵向检查,耗时2分钟。
- 检查时间与货物数量无关,只与检查模式有关。
请计算机器人检查完所有货物所需的最少时间。
输入格式
输入包含两行:
- 第一行是一个整数 ,表示货架的数量。
- 第二行包含 个整数 ,用空格分隔,表示每个货架的货物数量。
输出格式
输出一个整数,表示检查完所有货物所需的最少时间(以分钟为单位)。
样例输入1
3
5 5 5
样例输出1
1
样例输入2
5
2 2 1 2 1
样例输出2
4
样例输入3
5
7 4 3 3 5
样例输出3
6
样例解释
样例1 | 使用一次横向检查即可覆盖所有货物,耗时1分钟。 |
样例2 | 第一次横向检查覆盖15号货架的第1层(1分钟);第二次横向检查覆盖12号货架的第2层(1分钟);第三次纵向检查4号货架的第2层(2分钟)。总计4分钟。 |
样例3 | 第一次横向检查覆盖15号货架的13层(1分钟);第二次横向检查覆盖12号货架的第4层(1分钟);第三次纵向检查1号货架的57层(2分钟);第四次纵向检查5号货架的4~5层(2分钟)。总计6分钟。 |
数据范围
- ,其中
题解
DFS/记忆化搜索
本题暴力DFS应该也可以过,这里加一个记忆化数组来优化一下
关键思路是:对于任意一段连续的货架,我们有两种选择:
- 使用横向检查,覆盖这段货架的最低层,然后递归处理剩余的上层货物。
- 对每个货架单独使用纵向检查。
可以定义一个函数 dfs(left, right)
,表示检查从 left
到 right
号货架所需的最少时间。那么对于任意一段货架,可以这样计算:
- 找出这段货架中最矮的货架高度
minH
。 - 计算使用横向检查的成本:1分钟(横向检查最底层)+ 递归处理剩余上层货物的成本。
- 计算使用纵向检查的成本:每个货架2分钟。
- 取这两种方法中的最小值。
参考代码
- Python
import sys
sys.setrecursionlimit(10**7)
def dfs(left, right, shelf_heights, memo):
"""
深度优先搜索函数,计算检查从left到right货架所需的最少时间
参数:
left (int): 左边界货架索引
right (int): 右边界货架索引
shelf_heights (list): 货架高度列表
memo (dict): 记忆化搜索的缓存字典
返回:
int: 检查所需的最少时间
"""
if left > right:
return 0
if left == right:
return 2 # 单个货架默认使用纵向检查
# 检查是否已经计算过这个区间
if (left, right) in memo:
return memo[(left, right)]
min_height = min(shelf_heights[left:right+1])
horizontal_cost = 1 # 横向检查的基础成本
i = left
while i <= right:
if shelf_heights[i] > min_height:
start = i
while i <= right and shelf_heights[i] > min_height:
i += 1
horizontal_cost += dfs(start, i-1, shelf_heights, memo)
else:
i += 1
vertical_cost = 2 * (right - left + 1) # 纵向检查的总成本
# 选择成本较低的检查方式
result = min(horizontal_cost, vertical_cost)
memo[(left, right)] = result
return result
# 读取输入
n = int(input())
shelf_heights = list(map(int, input().split()))
memo = {}
# 计算并输出结果
result = dfs(0, n-1, shelf_heights, memo)
print(result)
- Java
import java.util.*;
public class Main {
static int[] shelfHeights;
static Map<String, Integer> memo = new HashMap<>();
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
shelfHeights = new int[n];
for (int i = 0; i < n; i++) {
shelfHeights[i] = scanner.nextInt();
}
int result = dfs(0, n - 1);
System.out.println(result);
}
/**
* 深度优先搜索函数,计算检查从left到right货架所需的最少时间
*
* @param left 左边界货架索引
* @param right 右边界货架索引
* @r
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
这里收集了超全的互联网春秋招笔试题,欢迎大家的订阅,会持续跟新的