当前位置: 首页 > article >正文

华为OD机试 - Excel单元格数值统计(Python/JS/C/C++ 2024 E卷 200分)

在这里插入图片描述

华为OD机试 2024E卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

Excel工作表中对选定区域的数值进行统计的功能非常实用。仿照Excel的这个功能,请你给定表格中区域中的单元格进行求和统计,并输出统计结果。

为简化计算,假设当前输入中每个单元格内容仅为数字或公式两种。

如果为数字,则是一个非负整数,形如3,77。
如果为公式,则固定以“=”开头,且包含以下三种情况:

  1. 等于某单元格的值,例如=B12;
  2. 两个单元格的双目运算(仅为+或-),形如=C1-C2,C3+B2;
  3. 单元格和数字的双目运算(仅为+或-),形如=B1+1,100-B2。

注意:

公式内容都是合法的,例如不存在=,=C+1,=C1-C2+B3=5,=3+5;
不存在循环引用,例如A1=B1+C1,C1=A1+B2;
内容中不存在空格、括号。

二、输入描述

第一行两个整数rows、cols,表示给定表格区域的行数和列数,1<=rows<=20,1<=cols<=26。
接下来rows行,每行cols个以空格分隔的字符串values,表示表格values的单元格内容。
最后一行给出一个字符串,表示给定的统计区域,形如A1

三、输出描述

一个整数,表示给定选定区域中单元格数字的累加总和,范围为-2,147,483,648 ~ 2,147,483,647。

四、测试用例

1、输入

1 3
1 =A1+C1 3
A1:C1

2、输出

8

3、说明

A1 = 1
B1 = A1 + C1 = 1 + 3 = 4
C1 = 3
总和 = 1 + 4 + 3 = 8

五、解题思路

题目要求对Excel工作表中选定区域的单元格进行求和统计。每个单元格的内容可能是一个数字或一个公式。

具体步骤

  1. 输入处理:
    • 读取表格的行数和列数。
    • 读取每个单元格的内容,并存储在一个二维数组中。
    • 读取需要统计的区域范围。
  2. 区域解析:
    • 解析统计区域的起始和结束单元格,例如“A1
    • ”表示从A1到C1的所有单元格。
    • 将单元格的字母部分(列)转换为数字索引,数字部分(行)转换为数组索引。
  3. 单元格值计算:
    • 对于每个单元格,如果是数字,直接取其值。
    • 如果是公式,需要解析公式并计算其结果。公式可能涉及其他单元格的值或直接的数值运算。
    • 使用递归或记忆化递归来处理公式中引用的单元格,避免重复计算。
  4. 求和:
    • 遍历选定区域内的所有单元格,计算每个单元格的值并累加。
  5. 输出结果。

六、Python算法源码

import sys

# 定义全局变量
table = []  # 存储表格内容的二维列表
memo = {}   # 记忆化存储已计算的单元格值
rows = 0    # 表格的行数
cols = 0    # 表格的列数

def cell_to_index(cell):
    """
    将单元格标识转换为行列索引
    例如:'A1' -> (0, 0)
    """
    col = 0
    i = 0
    # 处理列(字母部分)
    while i < len(cell) and cell[i].isalpha():
        col = col * 26 + (ord(cell[i].upper()) - ord('A') + 1)
        i += 1
    # 处理行(数字部分)
    row = int(cell[i:]) - 1
    return (row, col - 1)

def index_to_cell(row, col):
    """
    将行列索引转换为单元格标识
    例如:(0, 0) -> 'A1'
    """
    cell = ""
    col += 1
    while col > 0:
        rem = (col - 1) % 26
        cell = chr(ord('A') + rem) + cell
        col = (col - 1) // 26
    cell += str(row + 1)
    return cell

def evaluate(row, col):
    """
    计算指定单元格的值
    """
    cell = index_to_cell(row, col)
    # 如果已经计算过,直接返回记忆化的值
    if cell in memo:
        return memo[cell]
    
    content = table[row][col]
    if not content.startswith('='):
        # 如果是数字,直接转换为整数
        value = int(content)
    else:
        # 如果是公式,解析并计算表达式
        expr = content[1:]  # 去掉 '='
        value = evaluate_expression(expr)
    
    # 记忆化存储计算结果
    memo[cell] = value
    return value

def evaluate_expression(expr):
    """
    解析并计算表达式
    支持单个操作符 '+' 或 '-'
    """
    # 查找运算符的位置
    op_pos = -1
    op = ''
    for i, char in enumerate(expr):
        if char in ['+', '-']:
            op_pos = i
            op = char
            break
    if op_pos == -1:
        # 没有运算符,可能是单元格引用或数字
        return parse_term(expr)
    else:
        # 分割表达式为左半部分和右半部分
        left = expr[:op_pos]
        right = expr[op_pos+1:]
        left_val = parse_term(left)
        right_val = parse_term(right)
        if op == '+':
            return left_val + right_val
        else:
            return left_val - right_val

def parse_term(term):
    """
    解析单个项,可能是单元格引用或数字
    """
    if term[0].isalpha():
        # 如果是单元格引用,递归计算其值
        row, col = cell_to_index(term)
        return evaluate(row, col)
    else:
        # 如果是数字,直接转换为整数
        return int(term)

def main():
    global rows, cols, table
    # 读取输入
    input = sys.stdin.read().splitlines()
    # 第一行:行数和列数
    rows, cols = map(int, input[0].split())
    # 读取表格内容
    table = []
    for i in range(1, rows + 1):
        table.append(input[i].split())
    # 读取统计区域
    range_str = input[rows + 1]
    cells = range_str.split(':')
    start = cell_to_index(cells[0])
    end = cell_to_index(cells[1])
    # 计算总和
    total = 0
    for r in range(start[0], end[0] + 1):
        for c in range(start[1], end[1] + 1):
            total += evaluate(r, c)
    # 输出结果
    print(total)

if __name__ == "__main__":
    main()

七、JavaScript算法源码

const readline = require('readline');

// 创建接口以读取输入
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];
rl.on('line', function(line){
    input.push(line);
}).on('close', function(){
    // 开始处理输入
    let index = 0;
    // 读取行数和列数
    let [rows, cols] = input[index++].split(' ').map(Number);
    // 读取表格内容
    let table = [];
    for(let i=0; i<rows; i++){
        table.push(input[index++].split(' '));
    }
    // 读取统计区域
    let range = input[index++].trim();
    let cells = range.split(':');
    let start = cellToIndex(cells[0]);
    let end = cellToIndex(cells[1]);
    // 初始化记忆化存储
    let memo = new Map();
    // 计算总和
    let total = 0;
    for(let r = start.row; r <= end.row; r++){
        for(let c = start.col; c <= end.col; c++){
            total += evaluate(r, c);
        }
    }
    // 输出结果
    console.log(total);

    // 函数定义
    function cellToIndex(cell){
        let col = 0;
        let i = 0;
        while(i < cell.length && /[A-Z]/.test(cell[i])){
            col = col * 26 + (cell.charCodeAt(i) - 'A'.charCodeAt(0) + 1);
            i++;
        }
        let row = parseInt(cell.substring(i)) - 1;
        return {row: row, col: col - 1};
    }

    function indexToCell(row, col){
        let cell = "";
        col +=1;
        while(col >0){
            let rem = (col -1) %26;
            cell = String.fromCharCode('A'.charCodeAt(0) + rem) + cell;
            col = Math.floor((col -1)/26);
        }
        cell += (row +1).toString();
        return cell;
    }

    function evaluate(row, col){
        let cell = indexToCell(row, col);
        if(memo.has(cell)){
            return memo.get(cell);
        }
        let content = table[row][col];
        let value = 0;
        if(!content.startsWith('=')){
            value = parseInt(content);
        }
        else{
            let expr = content.substring(1);
            value = evaluateExpression(expr);
        }
        memo.set(cell, value);
        return value;
    }

    function evaluateExpression(expr){
        let opPos = -1;
        let op = '';
        for(let i=0; i<expr.length; i++){
            if(expr[i] === '+' || expr[i] === '-'){
                opPos = i;
                op = expr[i];
                break;
            }
        }
        if(opPos === -1){
            return parseTerm(expr);
        }
        else{
            let left = expr.substring(0, opPos);
            let right = expr.substring(opPos+1);
            let leftVal = parseTerm(left);
            let rightVal = parseTerm(right);
            return op === '+' ? leftVal + rightVal : leftVal - rightVal;
        }
    }

    function parseTerm(term){
        if(/[A-Z]/.test(term[0])){
            let idx = cellToIndex(term);
            return evaluate(idx.row, idx.col);
        }
        else{
            return parseInt(term);
        }
    }
});

八、C算法源码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX_ROWS 20
#define MAX_COLS 26
#define MAX_CELL_LEN 100
#define MAX_EXPR_LEN 1000

// 定义表格内容
char table[MAX_ROWS][MAX_COLS][MAX_CELL_LEN];
// 记忆化存储单元格值,初始化为未计算状态
long long memo_val[MAX_ROWS][MAX_COLS];
int memo_flag[MAX_ROWS][MAX_COLS] = {0};

// 表格的行数和列数
int rows, cols;

// 将单元格标识转换为行列索引
void cell_to_index(char *cell, int *row, int *col){
    *col = 0;
    int i = 0;
    // 处理列(字母部分)
    while(cell[i] && isalpha(cell[i])){
        *col = (*col) * 26 + (toupper(cell[i]) - 'A' + 1);
        i++;
    }
    // 处理行(数字部分)
    char num_part[MAX_CELL_LEN];
    int j = 0;
    while(cell[i]){
        num_part[j++] = cell[i++];
    }
    num_part[j] = '\0';
    *row = atoi(num_part) -1;
    *col = *col -1;
}

// 将行列索引转换为单元格标识
void index_to_cell(int row, int col, char *cell){
    cell[0] = '\0';
    col +=1;
    char temp[10];
    while(col >0){
        int rem = (col -1) %26;
        char c = 'A' + rem;
        sprintf(temp, "%c", c);
        strcat(cell, temp);
        col = (col -1) /26;
    }
    char row_str[10];
    sprintf(row_str, "%d", row +1);
    strcat(cell, row_str);
}

// 解析并计算表达式
long long evaluate_expression(char *expr);

// 解析单个项,可能是单元格引用或数字
long long parse_term(char *term){
    if(isalpha(term[0])){
        int r, c;
        cell_to_index(term, &r, &c);
        return evaluate(r, c);
    }
    else{
        return atoll(term);
    }
}

// 计算单元格的值
long long evaluate(int row, int col){
    // 如果已经计算过,直接返回
    if(memo_flag[row][col]){
        return memo_val[row][col];
    }
    char *content = table[row][col];
    long long value =0;
    if(content[0] != '='){
        // 直接是数字
        value = atoll(content);
    }
    else{
        // 是公式,解析并计算表达式
        char expr[MAX_EXPR_LEN];
        strcpy(expr, content +1); // 去掉 '='
        value = evaluate_expression(expr);
    }
    // 记忆化存储
    memo_val[row][col] = value;
    memo_flag[row][col] =1;
    return value;
}

// 解析并计算表达式
long long evaluate_expression(char *expr){
    int op_pos = -1;
    char op = 0;
    // 查找运算符的位置
    for(int i=0; i<strlen(expr); i++){
        if(expr[i] == '+' || expr[i] == '-'){
            op_pos = i;
            op = expr[i];
            break;
        }
    }
    if(op_pos == -1){
        // 没有运算符,可能是单元格引用或数字
        char term[MAX_CELL_LEN];
        strcpy(term, expr);
        return parse_term(term);
    }
    else{
        // 分割表达式为左半部分和右半部分
        char left[MAX_CELL_LEN];
        strncpy(left, expr, op_pos);
        left[op_pos] = '\0';
        char right[MAX_CELL_LEN];
        strcpy(right, expr + op_pos +1);
        long long left_val = parse_term(left);
        long long right_val = parse_term(right);
        if(op == '+'){
            return left_val + right_val;
        }
        else{
            return left_val - right_val;
        }
    }
}

int main(){
    // 读取行数和列数
    scanf("%d %d", &rows, &cols);
    // 读取表格内容
    for(int i=0; i<rows; i++){
        for(int j=0; j<cols; j++){
            scanf("%s", table[i][j]);
        }
    }
    // 读取统计区域
    char range[20];
    scanf("%s", range);
    // 解析统计区域的起始和结束单元格
    char *token = strtok(range, ":");
    char start_cell[MAX_CELL_LEN];
    char end_cell[MAX_CELL_LEN];
    strcpy(start_cell, token);
    token = strtok(NULL, ":");
    strcpy(end_cell, token);
    int start_r, start_c, end_r, end_c;
    cell_to_index(start_cell, &start_r, &start_c);
    cell_to_index(end_cell, &end_r, &end_c);
    // 计算总和
    long long total =0;
    for(int r=start_r; r<=end_r; r++){
        for(int c=start_c; c<=end_c; c++){
            total += evaluate(r, c);
        }
    }
    // 输出结果
    printf("%lld\n", total);
    return 0;
}

九、C++算法源码

#include <bits/stdc++.h>
using namespace std;

// 定义表格内容
vector<vector<string>> table;
// 记忆化存储单元格值
long long memo_val[21][27];
bool memo_flag[21][27];

// 表格的行数和列数
int rows, cols;

// 将单元格标识转换为行列索引
pair<int, int> cell_to_index(string cell){
    int col =0;
    int i=0;
    // 处理列(字母部分)
    while(i < cell.size() && isalpha(cell[i])){
        col = col *26 + (toupper(cell[i]) - 'A' +1);
        i++;
    }
    // 处理行(数字部分)
    int row = stoi(cell.substr(i)) -1;
    return {row, col -1};
}

// 将行列索引转换为单元格标识
string index_to_cell(int row, int col){
    string cell = "";
    col +=1;
    while(col >0){
        int rem = (col -1) %26;
        cell = char('A' + rem) + cell;
        col = (col -1)/26;
    }
    cell += to_string(row +1);
    return cell;
}

// 解析并计算表达式
long long evaluate_expression(string expr);

// 解析单个项,可能是单元格引用或数字
long long parse_term(string term){
    if(isalpha(term[0])){
        pair<int, int> idx = cell_to_index(term);
        return evaluate(idx.first, idx.second);
    }
    else{
        return stoll(term);
    }
}

// 计算单元格的值
long long evaluate(int row, int col){
    // 如果已经计算过,直接返回
    if(memo_flag[row][col]){
        return memo_val[row][col];
    }
    string content = table[row][col];
    long long value =0;
    if(content[0] != '='){
        // 直接是数字
        value = stoll(content);
    }
    else{
        // 是公式,解析并计算表达式
        string expr = content.substr(1); // 去掉 '='
        value = evaluate_expression(expr);
    }
    // 记忆化存储
    memo_val[row][col] = value;
    memo_flag[row][col] = true;
    return value;
}

// 解析并计算表达式
long long evaluate_expression(string expr){
    int op_pos = -1;
    char op = 0;
    // 查找运算符的位置
    for(int i=0; i<expr.size(); i++){
        if(expr[i] == '+' || expr[i] == '-'){
            op_pos = i;
            op = expr[i];
            break;
        }
    }
    if(op_pos == -1){
        // 没有运算符,可能是单元格引用或数字
        return parse_term(expr);
    }
    else{
        // 分割表达式为左半部分和右半部分
        string left = expr.substr(0, op_pos);
        string right = expr.substr(op_pos +1);
        long long left_val = parse_term(left);
        long long right_val = parse_term(right);
        if(op == '+'){
            return left_val + right_val;
        }
        else{
            return left_val - right_val;
        }
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    // 读取行数和列数
    cin >> rows >> cols;
    // 读取表格内容
    table.assign(rows, vector<string>(cols));
    for(int i=0; i<rows; i++){
        for(int j=0; j<cols; j++){
            cin >> table[i][j];
            memo_flag[i][j] = false;
        }
    }
    // 读取统计区域
    string range;
    cin >> range;
    // 解析统计区域的起始和结束单元格
    size_t pos = range.find(':');
    string start_cell = range.substr(0, pos);
    string end_cell = range.substr(pos +1);
    pair<int, int> start = cell_to_index(start_cell);
    pair<int, int> end = cell_to_index(end_cell);
    // 计算总和
    long long total =0;
    for(int r = start.first; r <= end.first; r++){
        for(int c = start.second; c <= end.second; c++){
            total += evaluate(r, c);
        }
    }
    // 输出结果
    cout << total << "\n";
    return 0;
}


🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述


http://www.kler.cn/news/335154.html

相关文章:

  • git | 合并 commit 的两种方法
  • 没有很深入的理解一下数字图像传感器
  • VL53L4CD液位监测(2)----液位检测
  • 足球青训管理:Spring Boot技术实现
  • 【python实操】python小程序之函数的方法和赋值的区别
  • MySQL 临时表
  • 利用 Qt 和 MySQL 实现简单的数据库用户登录与创建功能
  • Linux 安装 yum
  • 聊聊JIT是如何影响JVM性能的!
  • YOLO11改进|卷积篇|引入SPDConv
  • unity一键注释日志和反注释日志
  • Transformer 模型和 BERT 模型:概述
  • Python机器学习模型的部署与维护:版本管理、监控与更新策略
  • SpringCloudAlibaba的nacos启动注册实现
  • C0007.Clion中添加ui文件及运行的完整步骤
  • MySQL深度分页
  • TypeScript编译选项
  • 用人工智能写作:专业作家利用 ChatGPT 的五种方式 ✍️
  • 文心智能体——制作你的专属AI
  • 前缀和(8)_矩阵区域和