Bootstrap

华为OD机试 - 数组的中心位置(Python/JS/C/C++ 2024 E卷 100分)

在这里插入图片描述

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

五、解题思路

  1. 读取输入的整数数组nums
  2. 获取数组的长度n
  3. 初始化中间位置middlen / 2
  4. 初始化左边乘积的标志leftFlagtrue,右边乘积的标志rightFlagfalse
  5. 创建一个列表list,用于存储中心位置的下标。
  6. 进入一个无限循环,直到找到中心位置或完成搜索。
  7. 在循环中,计算左边数的乘积和右边数的乘积,并将它们进行比较。
  8. 如果左边乘积等于右边乘积,将当前中心位置加入到list中。
  9. 如果左边乘积的标志leftFlagtrue,将中心位置向左移动一位,如果已经到达数组的最左边,则将左边乘积的标志设为false,右边乘积的标志设为true,并将中心位置重置为n / 2
  10. 如果右边乘积的标志rightFlagtrue,将中心位置向右移动一位,如果已经到达数组的最右边,则退出循环。
  11. 循环结束后,检查列表list的大小。
  12. 如果列表为空,表示数组不存在中心位置,输出-1。
  13. 否则,将列表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算法的适用场景,发现新题目,随时更新。

在这里插入图片描述

;