华为OD机试 - 幻方修复(Python/JS/C/C++ 2025 B卷 200分)

在这里插入图片描述

2025B卷华为OD机试统一考试题库清单(持续收录中)以及考点说明(Python/JS/C/C++)。

专栏导读

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

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

一、题目描述

幻方(Magic Square)是一个由 1~N²,共 N² 个整数构成的 N*N 矩阵,满足每行、列和对角线上的数字和相等。

上回你已经帮助小明将写错一个数字的幻方进行了修复,小明在感激之余也想进一步试试你的水平,于是他准备了有两个数字发生了位置交换的幻方。

你可以把这两个交换的数字找出来并且改正吗?

二、输入描述

第一行输入一个整数 N,代表带校验幻方的阶数(3 ≤ N ≤ 50)
接下来的 N 行,每行 N 个整数,空格隔开(1 ≤ 每个整数 ≤ N²)

三、输出描述

输出两行,代表两条纠正信息,注意先输出行号小的,若行号相同则先输出列好小的

每行输出空格隔开的三个整数,分别是:出错行号、出错列号、应填入的数字(末尾无空格)

四、测试用例

测试用例1:

1、输入

3
8 1 9
3 5 7
4 6 2

2、输出

1 3 6
3 2 9

3、说明

将 6 和 9 交换位置后,得到输入的幻方。
输出需要修正的位置 (1,3) 应填 6,以及 (3,2) 应填 9。

五、解题思路

  1. 输入读取:
    • 使用 Scanner 从标准输入读取幻方的阶数 N。
    • 读取接下来的 N 行,每行 N 个整数,构成 N*N 的幻方矩阵 square。
  2. 魔数计算:
    • 魔数 M 计算公式为 M = N * (N² + 1) / 2,这是标准幻方的魔数公式。
  3. 检测错误行和列:
    • 遍历每一行,计算行和是否等于魔数 M。如果不等,将该行索引记录在 wrongRows 列表中。
    • 遍历每一列,计算列和是否等于魔数 M。如果不等,将该列索引记录在 wrongCols 列表中。
  4. 确定交换位置:
    • 假设只有两行和两列存在错误,分别记录为 r1, r2(行索引)和 c1, c2(列索引)。
    • 生成四个候选交换位置:(r1,c1) 和 (r2,c2),以及 (r1,c2) 和 (r2,c1)。
    • 尝试交换 (r1,c1) 和 (r2,c2),并检查幻方是否恢复正确。
    • 如果不正确,恢复交换,并尝试交换 (r1,c2) 和 (r2,c1),再次检查幻方是否正确。
    • 根据交换结果,输出需要修正的位置和正确的数字。
  5. 输出修正信息:
    • 根据交换后的结果,输出两个需要修正的位置,格式为 行号 列号 应填入的数字。
    • 行号和列号从 1 开始计数。
  6. 辅助函数:
    • swap: 用于交换幻方中两个位置的数字。
    • isValidMagicSquare: 检查当前幻方是否有效(所有行、列、对角线的和等于魔数)。

六、Python算法源码

class Correction:
    def __init__(self, r, c, correct_value):
        self.r = r  # 行号 (0-indexed)
        self.c = c  # 列号 (0-indexed)
        self.correct_value = correct_value # 应填入的数字

    def __lt__(self, other): # 用于排序
        if self.r != other.r:
            return self.r < other.r
        return self.c < other.c

    def __str__(self):
        return f"{self.r + 1} {self.c + 1} {self.correct_value}" # 输出时转为1-indexed

def is_magic_after_swap(original_matrix, r1, c1, new_val1, r2, c2, new_val2, n, magic_sum):
    # 检查行和
    for i in range(n):
        current_row_sum = 0
        for j in range(n):
            current_value = original_matrix[i][j]
            if i == r1 and j == c1:
                current_value = new_val1
            elif i == r2 and j == c2:
                current_value = new_val2
            current_row_sum += current_value
        if current_row_sum != magic_sum:
            return False

    # 检查列和
    for j in range(n):
        current_col_sum = 0
        for i in range(n):
            current_value = original_matrix[i][j]
            if i == r1 and j == c1:
                current_value = new_val1
            elif i == r2 and j == c2:
                current_value = new_val2
            current_col_sum += current_value
        if current_col_sum != magic_sum:
            return False

    # 检查主对角线和
    main_diag_sum = 0
    for i in range(n):
        current_value = original_matrix[i][i]
        if i == r1 and i == c1:
            current_value = new_val1
        elif i == r2 and i == c2:
            current_value = new_val2
        main_diag_sum += current_value
    if main_diag_sum != magic_sum:
        return False

    # 检查副对角线和
    anti_diag_sum = 0
    for i in range(n):
        current_value = original_matrix[i][n - 1 - i]
        if i == r1 and (n - 1 - i) == c1:
            current_value = new_val1
        elif i == r2 and (n - 1 - i) == c2:
            current_value = new_val2
        anti_diag_sum += current_value
    if anti_diag_sum != magic_sum:
        return False
    
    return True

def solve():
    n = int(input()) # 读取矩阵阶数 N
    matrix = [] # 存储矩阵
    for _ in range(n):
        matrix.append(list(map(int, input().split()))) # 读取一行矩阵元素

    n_squared = n * n
    magic_sum = n * (n_squared + 1) // 2 # 计算幻方的标准和

    corrections = []

    for r1 in range(n):
        for c1 in range(n):
            for r2 in range(n):
                for c2 in range(n):
                    if r1 == r2 and c1 == c2: # 不能是同一个单元格
                        continue
                    
                    val1 = matrix[r1][c1] # (r1,c1)处的原始值
                    val2 = matrix[r2][c2] # (r2,c2)处的原始值

                    # 模拟交换回来:(r1,c1)处应为val2, (r2,c2)处应为val1
                    if is_magic_after_swap(matrix, r1, c1, val2, r2, c2, val1, n, magic_sum):
                        corrections.append(Correction(r1, c1, val2))
                        corrections.append(Correction(r2, c2, val1))
                        
                        corrections.sort() # 排序
                        
                        for corr in corrections:
                            print(corr)
                        return

solve()

七、JavaScript算法源码

class Correction {
    constructor(r, c, correctValue) {
        this.r = r; // 行号 (0-indexed)
        this.c = c; // 列号 (0-indexed)
        this.correctValue = correctValue; // 应填入的数字
    }

    toString() {
        return `${this.r + 1} ${this.c + 1} ${this.correctValue}`; // 输出时转为1-indexed
    }
}

function compareCorrections(a, b) {
    if (a.r !== b.r) {
        return a.r - b.r; // 先按行号升序
    }
    return a.c - b.c; // 行号相同则按列号升序
}

function isMagicAfterSwap(originalMatrix, r1, c1, newVal1, r2, c2, newVal2, n, magicSum) {
    // 检查行和
    for (let i = 0; i < n; i++) {
        let currentRowSum = 0;
        for (let j = 0; j < n; j++) {
            let currentValue = originalMatrix[i][j];
            if (i === r1 && j === c1) {
                currentValue = newVal1;
            } else if (i === r2 && j === c2) {
                currentValue = newVal2;
            }
            currentRowSum += currentValue;
        }
        if (currentRowSum !== magicSum) {
            return false;
        }
    }

    // 检查列和
    for (let j = 0; j < n; j++) {
        let currentColSum = 0;
        for (let i = 0; i < n; i++) {
            let currentValue = originalMatrix[i][j];
            if (i === r1 && j === c1) {
                currentValue = newVal1;
            } else if (i === r2 && j === c2) {
                currentValue = newVal2;
            }
            currentColSum += currentValue;
        }
        if (currentColSum !== magicSum) {
            return false;
        }
    }

    // 检查主对角线和
    let mainDiagSum = 0;
    for (let i = 0; i < n; i++) {
        let currentValue = originalMatrix[i][i];
        if (i === r1 && i === c1) {
            currentValue = newVal1;
        } else if (i === r2 && i === c2) {
            currentValue = newVal2;
        }
        mainDiagSum += currentValue;
    }
    if (mainDiagSum !== magicSum) {
        return false;
    }

    // 检查副对角线和
    let antiDiagSum = 0;
    for (let i = 0; i < n; i++) {
        let currentValue = originalMatrix[i][n - 1 - i];
        if (i === r1 && (n - 1 - i) === c1) {
            currentValue = newVal1;
        } else if (i === r2 && (n - 1 - i) === c2) {
            currentValue = newVal2;
        }
        antiDiagSum += currentValue;
    }
    if (antiDiagSum !== magicSum) {
        return false;
    }
    
    return true;
}

function solve(inputLines) {
    let lineIdx = 0;
    const n = parseInt(inputLines[lineIdx++]); // 读取矩阵阶数 N
    const matrix = []; // 存储矩阵
    for (let i = 0; i < n; i++) {
        matrix.push(inputLines[lineIdx++].split(' ').map(Number)); // 读取一行矩阵元素
    }

    const nSquared = n * n;
    const magicSum = n * (nSquared + 1) / 2; // 计算幻方的标准和

    const corrections = [];

    for (let r1 = 0; r1 < n; r1++) {
        for (let c1 = 0; c1 < n; c1++) {
            for (let r2 = 0; r2 < n; r2++) {
                for (let c2 = 0; c2 < n; c2++) {
                    if (r1 === r2 && c1 === c2) { // 不能是同一个单元格
                        continue;
                    }
                    
                    const val1 = matrix[r1][c1]; // (r1,c1)处的原始值
                    const val2 = matrix[r2][c2]; // (r2,c2)处的原始值

                    // 模拟交换回来:(r1,c1)处应为val2, (r2,c2)处应为val1
                    if (isMagicAfterSwap(matrix, r1, c1, val2, r2, c2, val1, n, magicSum)) {
                        corrections.push(new Correction(r1, c1, val2));
                        corrections.push(new Correction(r2, c2, val1));
                        
                        corrections.sort(compareCorrections); // 排序
                        
                        corrections.forEach(corr => {
                            console.log(corr.toString());
                        });
                        return;
                    }
                }
            }
        }
    }
}

// --- 输入处理部分 (根据运行环境调整) ---
// 浏览器或Node.js环境读取输入的方式不同
// 假设输入是通过 Node.js 的 readline 模块或者一个预设的数组
// 例如,在 Node.js 中:
/*
const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
    terminal: false
});

let inputLines = [];
rl.on('line', (line) => {
    inputLines.push(line);
});

rl.on('close', () => {
    solve(inputLines);
});
*/

// 为了方便测试,可以直接提供输入数组:
// const testInput = [
//     "3",
//     "8 1 9",
//     "3 5 7",
//     "4 6 2"
// ];
// solve(testInput);
// const testInput2 = [
// "3",
// "7 2 6",
// "9 5 1",
// "4 3 8"
// ];
// solve(testInput2);


八、C算法源码

#include 
#include  // For qsort

typedef struct {
    int r, c, correct_value; // 行号、列号(0-indexed),应填入的数字
} Correction;

// qsort 比较函数
int compare_corrections(const void *a, const void *b) {
    Correction *corrA = (Correction *)a;
    Correction *corrB = (Correction *)b;
    if (corrA->r != corrB->r) {
        return corrA->r - corrB->r; // 先按行号升序
    }
    return corrA->c - corrB->c; // 行号相同则按列号升序
}

// 检查函数
int is_magic_after_swap(int n, int original_matrix[n][n], // 使用VLA,或者动态分配
                        int r1, int c1, int new_val1,
                        int r2, int c2, int new_val2,
                        long magic_sum) {
    // 检查行和
    for (int i = 0; i < n; i++) {
        long current_row_sum = 0;
        for (int j = 0; j < n; j++) {
            int current_value = original_matrix[i][j];
            if (i == r1 && j == c1) {
                current_value = new_val1;
            } else if (i == r2 && j == c2) {
                current_value = new_val2;
            }
            current_row_sum += current_value;
        }
        if (current_row_sum != magic_sum) {
            return 0; // false
        }
    }

    // 检查列和
    for (int j = 0; j < n; j++) {
        long current_col_sum = 0;
        for (int i = 0; i < n; i++) {
            int current_value = original_matrix[i][j];
            if (i == r1 && j == c1) {
                current_value = new_val1;
            } else if (i == r2 && j == c2) {
                current_value = new_val2;
            }
            current_col_sum += current_value;
        }
        if (current_col_sum != magic_sum) {
            return 0; // false
        }
    }

    // 检查主对角线和
    long main_diag_sum = 0;
    for (int i = 0; i < n; i++) {
        int current_value = original_matrix[i][i];
        if (i == r1 && i == c1) {
            current_value = new_val1;
        } else if (i == r2 && i == c2) {
            current_value = new_val2;
        }
        main_diag_sum += current_value;
    }
    if (main_diag_sum != magic_sum) {
        return 0; // false
    }

    // 检查副对角线和
    long anti_diag_sum = 0;
    for (int i = 0; i < n; i++) {
        int current_value = original_matrix[i][n - 1 - i];
        if (i == r1 && (n - 1 - i) == c1) {
            current_value = new_val1;
        } else if (i == r2 && (n - 1 - i) == c2) {
            current_value = new_val2;
        }
        anti_diag_sum += current_value;
    }
    if (anti_diag_sum != magic_sum) {
        return 0; // false
    }
    
    return 1; // true
}


int main() {
    int n;
    scanf("%d", &n); // 读取矩阵阶数 N

    // C99 支持 VLA (Variable Length Array),如果编译器不支持,需要动态分配
    int matrix[n][n]; // 存储矩阵 
    // 或者使用动态分配:
    // int **matrix = (int **)malloc(n * sizeof(int *));
    // for (int i = 0; i < n; i++) {
    //     matrix[i] = (int *)malloc(n * sizeof(int));
    // }

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%d", &matrix[i][j]); // 读取矩阵元素
        }
    }

    long n_squared = (long)n * n;
    long magic_sum = n * (n_squared + 1) / 2; // 计算幻方的标准和

    Correction corrections[2]; // 最多两条纠正信息
    int found_count = 0;

    for (int r1 = 0; r1 < n; r1++) {
        for (int c1 = 0; c1 < n; c1++) {
            for (int r2 = 0; r2 < n; r2++) {
                for (int c2 = 0; c2 < n; c2++) {
                    if (r1 == r2 && c1 == c2) { // 不能是同一个单元格
                        continue;
                    }
                    
                    int val1 = matrix[r1][c1]; // (r1,c1)处的原始值
                    int val2 = matrix[r2][c2]; // (r2,c2)处的原始值

                    if (is_magic_after_swap(n, matrix, r1, c1, val2, r2, c2, val1, magic_sum)) {
                        corrections[0].r = r1;
                        corrections[0].c = c1;
                        corrections[0].correct_value = val2;

                        corrections[1].r = r2;
                        corrections[1].c = c2;
                        corrections[1].correct_value = val1;
                        
                        found_count = 2;
                        break; // 内层 c2 循环
                    }
                }
                if (found_count) break; // 内层 r2 循环
            }
            if (found_count) break; // 外层 c1 循环
        }
        if (found_count) break; // 外层 r1 循环
    }

    if (found_count) {
        qsort(corrections, 2, sizeof(Correction), compare_corrections); // 排序
        for (int i = 0; i < 2; i++) {
            // 输出时转为1-indexed
            printf("%d %d %d\n", corrections[i].r + 1, corrections[i].c + 1, corrections[i].correct_value);
        }
    }
    
    // 如果是动态分配的,记得释放内存
    // for (int i = 0; i < n; i++) {
    //     free(matrix[i]);
    // }
    // free(matrix);

    return 0;
}

九、C++算法源码

#include 
#include 
#include    // For std::accumulate (optional, can sum manually)
#include  // For std::sort

struct Correction {
    int r, c, correct_value; // 行号、列号(0-indexed),应填入的数字

    // 用于排序的比较运算符
    bool operator<(const Correction& other) const {
        if (r != other.r) {
            return r < other.r; // 先按行号升序
        }
        return c < other.c; // 行号相同则按列号升序
    }
};

// 检查函数
bool is_magic_after_swap(const std::vector<std::vector<int>>& original_matrix,
                         int r1, int c1, int new_val1,
                         int r2, int c2, int new_val2,
                         int n, long magic_sum) {
    // 检查行和
    for (int i = 0; i < n; ++i) {
        long current_row_sum = 0;
        for (int j = 0; j < n; ++j) {
            int current_value = original_matrix[i][j];
            if (i == r1 && j == c1) {
                current_value = new_val1;
            } else if (i == r2 && j == c2) {
                current_value = new_val2;
            }
            current_row_sum += current_value;
        }
        if (current_row_sum != magic_sum) {
            return false;
        }
    }

    // 检查列和
    for (int j = 0; j < n; ++j) {
        long current_col_sum = 0;
        for (int i = 0; i < n; ++i) {
            int current_value = original_matrix[i][j];
            if (i == r1 && j == c1) {
                current_value = new_val1;
            } else if (i == r2 && j == c2) {
                current_value = new_val2;
            }
            current_col_sum += current_value;
        }
        if (current_col_sum != magic_sum) {
            return false;
        }
    }

    // 检查主对角线和
    long main_diag_sum = 0;
    for (int i = 0; i < n; ++i) {
        int current_value = original_matrix[i][i];
        if (i == r1 && i == c1) {
            current_value = new_val1;
        } else if (i == r2 && i == c2) {
            current_value = new_val2;
        }
        main_diag_sum += current_value;
    }
    if (main_diag_sum != magic_sum) {
        return false;
    }

    // 检查副对角线和
    long anti_diag_sum = 0;
    for (int i = 0; i < n; ++i) {
        int current_value = original_matrix[i][n - 1 - i];
        if (i == r1 && (n - 1 - i) == c1) {
            current_value = new_val1;
        } else if (i == r2 && (n - 1 - i) == c2) {
            current_value = new_val2;
        }
        anti_diag_sum += current_value;
    }
    if (anti_diag_sum != magic_sum) {
        return false;
    }
    
    return true;
}

int main() {
    std::ios_base::sync_with_stdio(false); // 加速C++ IO
    std::cin.tie(NULL);

    int n;
    std::cin >> n; // 读取矩阵阶数 N

    std::vector<std::vector<int>> matrix(n, std::vector<int>(n)); // 存储矩阵
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            std::cin >> matrix[i][j]; // 读取矩阵元素
        }
    }

    long n_squared = (long)n * n;
    long magic_sum = n * (n_squared + 1) / 2; // 计算幻方的标准和

    std::vector<Correction> corrections;

    for (int r1 = 0; r1 < n; ++r1) {
        for (int c1 = 0; c1 < n; ++c1) {
            for (int r2 = 0; r2 < n; ++r2) {
                for (int c2 = 0; c2 < n; ++c2) {
                    if (r1 == r2 && c1 == c2) { // 不能是同一个单元格
                        continue;
                    }
                    
                    int val1 = matrix[r1][c1]; // (r1,c1)处的原始值
                    int val2 = matrix[r2][c2]; // (r2,c2)处的原始值

                    if (is_magic_after_swap(matrix, r1, c1, val2, r2, c2, val1, n, magic_sum)) {
                        corrections.push_back({r1, c1, val2});
                        corrections.push_back({r2, c2, val1});
                        
                        std::sort(corrections.begin(), corrections.end()); // 排序
                        
                        for (const auto& corr : corrections) {
                            // 输出时转为1-indexed
                            std::cout << corr.r + 1 << " " << corr.c + 1 << " " << corr.correct_value << "\n";
                        }
                        return 0; // 找到即退出
                    }
                }
            }
        }
    }

    return 0;
}



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

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

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

在这里插入图片描述

你可能感兴趣的:(搬砖工逆袭Java架构师,华为od,python,javascript,华为OD机试,2025B卷)