2025华为OD机试题库(按算法分类):2025华为OD统一考试题库清单(持续收录中)以及考点说明(Python/JS/C/C++)。
专栏导读
本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。
一、题目描述
给你一个整数数组nums,请计算数组的中心位置,数组的中心位置是数组的一个下标,其左侧所有元素相乘的积等于右侧所有元素相乘的积。数组第一个元素的左侧积为1,最后一个元素的右侧积为1。如果数组有多个中心位置,应该返回最靠近左边的那一个,如果数组不存在中心位置,返回-1。
二、输入描述
输入只有一行,给出N个正整数用空格分隔,nums = 2 5 3 6 5 6
1 <= nums.length <= 1024
1 <= nums[i] <= 10
三、输出描述
3
四、测试用例
1、输入
2 5 3 6 5 6
2、输出
3
五、解题思路
- 读取输入的整数数组
nums
。 - 获取数组的长度
n
。 - 初始化中间位置
middle
为n / 2
。 - 初始化左边乘积的标志
leftFlag
为true
,右边乘积的标志rightFlag
为false
。 - 创建一个列表
list
,用于存储中心位置的下标。 - 进入一个无限循环,直到找到中心位置或完成搜索。
- 在循环中,计算左边数的乘积和右边数的乘积,并将它们进行比较。
- 如果左边乘积等于右边乘积,将当前中心位置加入到
list
中。 - 如果左边乘积的标志
leftFlag
为true
,将中心位置向左移动一位,如果已经到达数组的最左边,则将左边乘积的标志设为false
,右边乘积的标志设为true
,并将中心位置重置为n / 2
。 - 如果右边乘积的标志
rightFlag
为true
,将中心位置向右移动一位,如果已经到达数组的最右边,则退出循环。 - 循环结束后,检查列表
list
的大小。 - 如果列表为空,表示数组不存在中心位置,输出-1。
- 否则,将列表
list
排序,并输出最靠近左边的中心位置的下标。
该算法的时间复杂度为O(N)
,其中N是数组的长度。在最坏情况下,需要遍历整个数组来计算左边和右边的乘积。最终的空间复杂度取决于列表list的大小,即O(1)
到O(N)
之间。
六、Python算法源码
def main():
import sys
# 读取标准输入,并去掉首尾空白字符
data = sys.stdin.read().strip()
if not data:
print(-1)
return
# 按空格分割输入字符串,得到数字字符串列表
parts = data.split()
n = len(parts)
# 将字符串列表转换为整数列表(Python 内置大整数支持)
nums = [int(x) for x in parts]
# 构造前缀乘积数组,prefix[i]表示从索引0到i-1的乘积,若 i==0 则为1
prefix = [1] * n
for i in range(1, n):
prefix[i] = prefix[i-1] * nums[i-1]
# 构造后缀乘积数组,suffix[i]表示从索引i+1到n-1的乘积,若 i==n-1 则为1
suffix = [1] * n
for i in range(n-2, -1, -1):
suffix[i] = suffix[i+1] * nums[i+1]
# 遍历所有下标,判断左右乘积是否相等
for i in range(n):
if prefix[i] == suffix[i]:
print(i)
return
# 若没有找到满足条件的下标,输出 -1
print(-1)
if __name__ == '__main__':
main()
七、JavaScript算法源码
function main() {
// 读取标准输入,使用 fs 模块同步读取
let input = require('fs').readFileSync(0, 'utf-8').trim();
if (!input) {
console.log(-1);
return;
}
// 按空格分割输入字符串,得到数字字符串数组
let parts = input.split(/\s+/);
let n = parts.length;
// 将字符串数组转换为 BigInt 数组(避免大数溢出)
let nums = parts.map(x => BigInt(x));
// 初始化前缀乘积数组,prefix[i] 表示从索引 0 到 i-1 的乘积,i==0 时为 1n
let prefix = new Array(n).fill(1n);
for (let i = 1; i < n; i++){
prefix[i] = prefix[i-1] * nums[i-1];
}
// 初始化后缀乘积数组,suffix[i] 表示从索引 i+1 到 n-1 的乘积,i==n-1 时为 1n
let suffix = new Array(n).fill(1n);
for (let i = n - 2; i >= 0; i--){
suffix[i] = suffix[i+1] * nums[i+1];
}
// 遍历每个下标,若左右乘积相等,则输出该下标
for (let i = 0; i < n; i++){
if (prefix[i] === suffix[i]) {
console.log(i);
return;
}
}
// 若不存在满足条件的下标,则输出 -1
console.log(-1);
}
main();
八、C算法源码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main() {
char buffer[8192];
// 从标准输入中读取一行数据
if (!fgets(buffer, sizeof(buffer), stdin)) {
printf("-1\n");
return 0;
}
// 去除换行符
buffer[strcspn(buffer, "\n")] = 0;
// 分割输入字符串,按空格获取各个数字
char* token = strtok(buffer, " ");
int nums[1024];
int n = 0;
while (token != NULL && n < 1024) {
nums[n++] = atoi(token);
token = strtok(NULL, " ");
}
double prefix[1024];
double suffix[1024];
// 初始化前缀对数和数组:prefix[i]表示从索引0到i-1各数字取对数后的和,若i==0则为 log(1) = 0
prefix[0] = 0.0;
for (int i = 1; i < n; i++){
prefix[i] = prefix[i-1] + log(nums[i-1]);
}
// 初始化后缀对数和数组:suffix[i]表示从索引i+1到n-1各数字取对数后的和,若i==n-1则为 0
suffix[n-1] = 0.0;
for (int i = n - 2; i >= 0; i--){
suffix[i] = suffix[i+1] + log(nums[i+1]);
}
// 使用一个很小的 eps 值判断浮点数是否“相等”
double eps = 1e-9;
for (int i = 0; i < n; i++){
if (fabs(prefix[i] - suffix[i]) < eps) {
printf("%d\n", i);
return 0;
}
}
// 若没有满足条件的下标,则输出 -1
printf("-1\n");
return 0;
}
九、C++算法源码
#include <iostream>
#include <sstream>
#include <vector>
#include <cmath>
#include <cstdlib>
using namespace std;
int main(){
string line;
// 从标准输入中读取一行数据
if(!getline(cin, line)){
cout << -1 << endl;
return 0;
}
// 使用字符串流将输入按空格拆分成数字
istringstream iss(line);
vector<int> nums;
int num;
while(iss >> num){
nums.push_back(num);
}
int n = nums.size();
// 初始化前缀对数和数组,prefix[i] 表示从索引 0 到 i-1 数字取对数后的和
vector<double> prefix(n, 0.0), suffix(n, 0.0);
prefix[0] = 0.0; // log(1)
for(int i = 1; i < n; i++){
prefix[i] = prefix[i-1] + log(nums[i-1]);
}
// 初始化后缀对数和数组,suffix[i] 表示从索引 i+1 到 n-1 数字取对数后的和
suffix[n-1] = 0.0;
for(int i = n - 2; i >= 0; i--){
suffix[i] = suffix[i+1] + log(nums[i+1]);
}
// 设置误差范围 eps 用于浮点数比较
double eps = 1e-9;
for(int i = 0; i < n; i++){
if(fabs(prefix[i] - suffix[i]) < eps){
cout << i << endl;
return 0;
}
}
// 若没有满足条件的下标,则输出 -1
cout << -1 << endl;
return 0;
}
🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)
🏆本文收录于,华为OD机试真题(Python/JS/C/C++)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。