华为秋招算法题解析:一元一次方程求解实战
1. 华为秋招算法题解析一元一次方程求解实战刚做完华为2025秋招的机试题第三题是一道看似简单但暗藏玄机的一元一次方程求解。题目要求处理形如2x-35x的字符串方程输出x的解。作为参加过多次大厂机考的老手我分享一下这道题的解题思路和三种语言的实现方案。这道题在华为OD机考中属于300分的中等难度题目主要考察字符串处理、数学思维和边界条件处理能力。虽然题目本身是初中数学内容但要在有限时间内写出健壮的代码并不容易。下面我会从问题分析、核心算法、多语言实现和测试技巧四个维度详细拆解。2. 问题分析与数学建模2.1 题目要求详解给定一个字符串形式的一元一次方程例如x53x-2-2x-x432x要求程序返回x的解结果用最简分数表示如1/2。如果方程无解返回No solution有无穷解返回Infinite solutions。2.2 数学原理拆解一元一次方程的标准形式为ax b 0解为x -b/a。我们需要将任意形式的方程转换为这种标准形式将方程两边分解为x的系数a和常数项b合并同类项得到a₁x b₁ a₂x b₂移项得到(a₁-a₂)x (b₂-b₁)最终a a₁-a₂b b₂-b₁2.3 边界条件分析需要特殊处理的情况除数为零时a0且b0 → 无穷解a0但b≠0 → 无解结果为整数时应表示为整数形式如2而非2/1需要约分到最简分数形式3. 核心算法设计与实现3.1 字符串解析方案解析方程字符串是本题的核心难点我采用双指针法进行词法分析def parse_expression(s): tokens [] i 0 while i len(s): if s[i] in -: sign -1 if s[i] - else 1 i 1 num 0 while i len(s) and s[i].isdigit(): num num * 10 int(s[i]) i 1 if i len(s) and s[i] x: tokens.append(sign * (num if num ! 0 else 1)) i 1 else: tokens.append(sign * num) elif s[i] x: tokens.append(1) i 1 elif s[i].isdigit(): num 0 while i len(s) and s[i].isdigit(): num num * 10 int(s[i]) i 1 if i len(s) and s[i] x: tokens.append(num) i 1 else: tokens.append(num) else: i 1 return tokens3.2 系数合并算法将解析出的token列表转换为系数和常数项public static int[] calculateCoefficients(ListInteger tokens) { int a 0, b 0; for (int token : tokens) { if (token ! 0) { if (tokens.indexOf(token) tokens.size() - 1 tokens.get(tokens.indexOf(token) 1) -1) { a token; // x的系数 } else { b token; // 常数项 } } } return new int[]{a, b}; }3.3 分数化简方法使用欧几里得算法求最大公约数int gcd(int a, int b) { return b 0 ? a : gcd(b, a % b); } string simplify(int numerator, int denominator) { if (denominator 0) return No solution; if (numerator 0) return Infinite solutions; int common_divisor gcd(abs(numerator), abs(denominator)); numerator / common_divisor; denominator / common_divisor; if (denominator 0) { numerator * -1; denominator * -1; } if (denominator 1) return to_string(numerator); return to_string(numerator) / to_string(denominator); }4. 多语言完整实现4.1 Java解决方案import java.util.*; public class Main { public static void main(String[] args) { Scanner sc new Scanner(System.in); String equation sc.nextLine(); String[] parts equation.split(); int[] left parseSide(parts[0]); int[] right parseSide(parts[1]); int a left[0] - right[0]; int b right[1] - left[1]; if (a 0 b 0) { System.out.println(Infinite solutions); } else if (a 0) { System.out.println(No solution); } else { int gcd gcd(Math.abs(a), Math.abs(b)); a / gcd; b / gcd; if (a 0) { a * -1; b * -1; } if (a 1) { System.out.println(b); } else { System.out.println(b / a); } } } private static int[] parseSide(String s) { int a 0, b 0; String[] tokens s.replace(-, -).split(\\); for (String token : tokens) { if (token.isEmpty()) continue; if (token.contains(x)) { String num token.replace(x, ); if (num.isEmpty()) a 1; else if (num.equals(-)) a -1; else a Integer.parseInt(num); } else { if (!token.isEmpty()) b Integer.parseInt(token); } } return new int[]{a, b}; } private static int gcd(int a, int b) { return b 0 ? a : gcd(b, a % b); } }4.2 C解决方案#include iostream #include string #include algorithm using namespace std; pairint, int parseSide(const string s) { int a 0, b 0; string token; int sign 1; for (int i 0; i s.size(); i) { if (s[i] || s[i] -) { if (!token.empty()) { if (token.back() x) { token.pop_back(); a sign * (token.empty() ? 1 : stoi(token)); } else { b sign * stoi(token); } token.clear(); } sign (s[i] ) ? 1 : -1; } else { token s[i]; } } if (!token.empty()) { if (token.back() x) { token.pop_back(); a sign * (token.empty() ? 1 : stoi(token)); } else { b sign * stoi(token); } } return {a, b}; } int gcd(int a, int b) { return b 0 ? a : gcd(b, a % b); } string solveEquation(string equation) { size_t equal_pos equation.find(); auto left parseSide(equation.substr(0, equal_pos)); auto right parseSide(equation.substr(equal_pos 1)); int a left.first - right.first; int b right.second - left.second; if (a 0 b 0) return Infinite solutions; if (a 0) return No solution; int common_divisor gcd(abs(a), abs(b)); a / common_divisor; b / common_divisor; if (a 0) { a -a; b -b; } if (a 1) return to_string(b); return to_string(b) / to_string(a); } int main() { string equation; getline(cin, equation); cout solveEquation(equation) endl; return 0; }4.3 Python解决方案import re from math import gcd def solve_equation(equation): left, right equation.split() def parse(s): tokens re.findall(([-]?\\d*x|^[-]?\\d), s) a, b 0, 0 for token in tokens: if x in token: num token.replace(x, ) if not num or num : a 1 elif num -: a - 1 else: a int(num) else: if token: b int(token) return a, b a1, b1 parse(left) a2, b2 parse(right) a a1 - a2 b b2 - b1 if a 0 and b 0: return Infinite solutions if a 0: return No solution common_divisor gcd(a, b) a // common_divisor b // common_divisor if a 0: a, b -a, -b if a 1: return str(b) return f{b}/{a} equation input().strip() print(solve_equation(equation))5. 测试技巧与常见陷阱5.1 必须考虑的测试用例常规情况x53x-2 → 7/22xx → 0边界情况xx → Infinite solutionsxx1 → No solution-x-1 → 1特殊格式32x → 12x35 → 10x0 → Infinite solutions5.2 华为机考实战技巧时间分配300分题建议在25分钟内完成包括5分钟分析题目15分钟编码5分钟测试调试技巧先处理简单情况如x1逐步增加复杂度处理系数、常数项最后处理符号和边界条件代码风格使用清晰的变量名a_coef, b_const等提取重复逻辑为独立方法添加关键注释5.3 常见错误排查符号处理错误忘记处理-x情况连续符号如2-3x解析错误系数识别错误x应视为1x-x应视为-1x除零错误没有检查a0的情况约分时未处理负数情况输出格式忘记约分整数结果输出为分数6. 算法优化与扩展思考6.1 性能优化方向使用有限状态机(FSM)替代正则表达式减少内存分配提升大字符串处理效率预处理字符串统一去除空格标准化符号如x→1x并行解析左右两边可以并行处理适合多核处理器环境6.2 题目扩展变种支持括号如2(x1)3(x-2)需要先展开表达式支持小数系数如0.5x1.25需要转换为整数处理支持多元方程如xy3需要线性代数知识6.3 工程实践建议防御性编程检查输入合法性处理异常输入格式单元测试覆盖边界条件测试随机生成测试用例API设计支持多种输出格式提供详细错误信息这道题虽然数学简单但完整实现需要考虑各种边界条件和异常处理非常考验工程实现能力。在华为OD机考中类似的字符串处理题目经常出现建议重点掌握这种双指针解析和状态机处理的技巧。

相关新闻

Dart之数据类型

Dart之数据类型

一、前言学习 Dart 数据类型时,可以先想象一个超市。超市里有饮料、蔬菜、水果、零食、日用品。不同商品不能全部随便塞进同一个容器里:鸡蛋需要防摔的盒子,饮料需要瓶子,散装糖果需要袋子,冷冻食品需要冷柜。代码里的…

2026/10/27 11:38:10 阅读更多 →
炉石传说HsMod插件:32倍速加速与200+皮肤定制完全指南

炉石传说HsMod插件:32倍速加速与200+皮肤定制完全指南

炉石传说HsMod插件:32倍速加速与200皮肤定制完全指南 【免费下载链接】HsMod Hearthstone Modification Based on BepInEx 项目地址: https://gitcode.com/GitHub_Trending/hs/HsMod HsMod是一款基于BepInEx框架开发的炉石传说游戏增强插件,为玩家…

2026/10/27 11:37:32 阅读更多 →
Frida动态注入技术:绕过安卓APP抓包检测的三种实战方案

Frida动态注入技术:绕过安卓APP抓包检测的三种实战方案

1. 项目概述:当抓包工具遇上“隐身”的APP搞安卓逆向和渗透测试的朋友,估计都遇到过这种让人头疼的情况:你兴冲冲地打开Burp Suite或者Charles,配置好代理和证书,准备对目标APP来一波流量分析,结果APP一启动…

2026/10/27 13:32:25 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/27 17:33:32 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/28 7:28:00 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/28 9:02:11 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/27 18:20:50 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/28 9:00:54 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/28 7:29:02 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/27 13:55:19 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/28 9:01:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/27 19:19:37 阅读更多 →