1. 问题背景与理解今天我们来拆解LeetCode第964题Least Operators to Express Number。这是一道关于数学表达式优化的题目要求我们找到用最少运算符表示目标数字的方法。题目描述如下给定一个正整数x和一个目标数target我们需要构造一个表达式这个表达式只能包含数字x、运算符加、减、乘、除和括号且最终结果等于target。我们的目标是找到使用运算符数量最少的表达式并返回这个最少的运算符数量。举个例子如果x3target19那么最优表达式是33333/3共使用了5个运算符4个乘号和1个加号。注意这里的除法是整数除法只保留整数部分。2. 解题思路分析2.1 问题分解这道题的核心在于如何将目标数target表示为x的不同幂次的组合。我们可以将target分解为x的幂次的线性组合target a₀x⁰ a₁x¹ a₂x² ... aₙxⁿ其中每个系数aᵢ的取值范围是0 ≤ aᵢ x。这样分解后我们需要计算每个幂次项所需的运算符数量。2.2 运算符计数规则对于每个幂次项aᵢxⁱ计算其运算符数量的规则如下当i0时即x⁰1表示1需要1个运算符即写x/x当i0时表示xⁱ需要i-1个乘法运算符系数aᵢ需要aᵢ-1个加法运算符因为要相加aᵢ次各项之间需要1个加法运算符连接2.3 递归解法这个问题非常适合用递归来解决。我们可以考虑target与x的不同幂次的关系如果target x我们可以直接用target个1相加或者用(x - target)个1相减如果target是x的幂次直接使用乘法表示否则将target表示为x的某个幂次的倍数加上余数或者表示为下一个幂次减去差值3. C语言实现详解3.1 递归函数设计我们设计一个递归函数leastOpsExpressTarget它接受当前基数x、目标数target和当前幂次k作为参数int leastOpsExpressTarget(int x, int target, int k) { if (target 0) return 0; if (target 1) return k 0 ? 2 : k; int quotient target / x; int remainder target % x; int cost remainder * (k 0 ? 2 : k); int option1 cost leastOpsExpressTarget(x, quotient, k 1); if (remainder ! 0) { cost (x - remainder) * (k 0 ? 2 : k); int option2 cost leastOpsExpressTarget(x, quotient 1, k 1); return option1 option2 ? option1 : option2; } return option1; }3.2 主函数调用主函数只需要调用上述递归函数初始时k0int leastOpsExpressTarget(int x, int target) { return leastOpsExpressTarget(x, target, 0) - 1; }这里减1是因为递归计算中会多算一个运算符。3.3 代码解析基本情况处理当target为0时不需要任何运算符当target为1时如果k0需要2个运算符x/x否则需要k个运算符分解target计算target除以x的商和余数计算用余数表示的成本递归计算用商表示的成本两种选择用quotient * x^k remainder * x^(k-1)用(quotient1) * x^k - (x-remainder) * x^(k-1)取两者中成本较小的4. 动态规划优化4.1 记忆化递归为了避免重复计算我们可以使用记忆化技术#define MAX_TARGET 1000000 int memo[MAX_TARGET][20]; // 假设k不会超过20 int leastOpsExpressTarget(int x, int target, int k) { if (target 0) return 0; if (target 1) return k 0 ? 2 : k; if (memo[target][k] ! 0) return memo[target][k]; int quotient target / x; int remainder target % x; int cost remainder * (k 0 ? 2 : k); int option1 cost leastOpsExpressTarget(x, quotient, k 1); if (remainder ! 0) { cost (x - remainder) * (k 0 ? 2 : k); int option2 cost leastOpsExpressTarget(x, quotient 1, k 1); memo[target][k] option1 option2 ? option1 : option2; } else { memo[target][k] option1; } return memo[target][k]; }4.2 迭代式动态规划我们也可以使用自底向上的动态规划方法int leastOpsExpressTarget(int x, int target) { int dp[1000000] {0}; for (int i 1; i target; i) { int quotient i / x; int remainder i % x; int cost remainder * (quotient 0 ? 2 : 1); int option1 cost dp[quotient]; if (remainder ! 0) { cost (x - remainder) * (quotient 0 ? 2 : 1); int option2 cost dp[quotient 1]; dp[i] option1 option2 ? option1 : option2; } else { dp[i] option1; } } return dp[target] - 1; }5. 复杂度分析与优化5.1 时间复杂度原始递归解法的时间复杂度为O(2^logₓ(target))因为每次递归都有两种选择。使用记忆化后时间复杂度降为O(logₓ(target))因为每个(target, k)组合只会计算一次。5.2 空间复杂度记忆化递归的空间复杂度为O(target * logₓ(target))因为需要存储所有可能的(target, k)组合的结果。5.3 进一步优化我们可以观察到k的值实际上与target的位数相关因此可以限制k的最大值从而减少空间使用#define MAX_K 20 int leastOpsExpressTarget(int x, int target) { int dp[1000000][MAX_K] {0}; // 其余代码保持不变 }6. 边界条件与测试用例6.1 常见测试用例int main() { printf(%d\n, leastOpsExpressTarget(3, 19)); // 输出: 5 printf(%d\n, leastOpsExpressTarget(5, 501)); // 输出: 8 printf(%d\n, leastOpsExpressTarget(2, 125046)); // 输出: 50 printf(%d\n, leastOpsExpressTarget(3, 929)); // 输出: 19 printf(%d\n, leastOpsExpressTarget(5, 365)); // 输出: 17 return 0; }6.2 边界情况处理需要特别注意以下边界情况x1的情况题目保证x≥2target0的情况题目保证target≥1target1的情况需要特殊处理targetx的情况直接返回0大数情况注意整数溢出7. 实际应用与扩展7.1 实际应用场景这类问题在实际中有多种应用编译器优化寻找最优的表达式计算方式硬件设计设计最节省资源的计算电路密码学寻找最紧凑的数字表示方法7.2 问题变种这个问题可以有多种变种允许使用更多运算符如指数不同的运算符成本如乘法比加法成本高多个基数的组合如同时使用2和37.3 性能优化建议对于非常大的target值可以考虑以下优化使用更高效的数据结构存储中间结果并行计算不同的递归分支使用数学方法寻找规律减少计算量8. 常见错误与调试技巧8.1 常见错误忘记处理k0时的特殊情况递归终止条件不完整运算符计数错误多算或少算整数溢出问题记忆化存储的键设计不当8.2 调试技巧打印递归调用树观察计算过程对小规模用例手动计算验证检查中间结果的合理性使用断言验证关键假设逐步增加问题规模观察性能变化我在实际解决这个问题时发现最容易出错的地方是运算符数量的计算。特别是在k0时即x⁰1需要用两个运算符表示x/x而其他幂次则可以用k个乘法表示xⁱ。这个细节需要特别注意否则会导致计算结果偏差。
企业数字化 ERP 产品动态
相关推荐
10个经典BASIC小程序:在6502上重温早期编程乐趣 早期编程的乐趣,现在很多人已经体会不到了。那个内存按KB算、主频按MHz算的年代,写代码是一件极其克制的事情——每一行都要算计着用,每一个字节都要抠着花。Microsoft BASIC M6502 就是那个时代的产物,它跑在6502处理器上&#x… · 2026/11/2 14:33:45
Paperclip:轻量级AI Agent编排协议与OpenClaw执行器契约设计 1. “Paperclip”不是回形针:它正在悄悄改写AI Agent的底层逻辑 最近在几个技术社区里频繁刷到“paperclip”这个词,点进去一看,既不是办公用品测评,也不是手工艺教程,而是一群人在讨论一个叫 Paperclip 的开源项目——… · 2026/11/2 14:33:45
回形针不简单:从发明历史到材质工艺的全面解析与避坑指南 1. 回形针这东西,远比你想象的复杂一支回形针,几毛钱一盒,办公室里一堆一堆地丢。但你真把它拿在手里端详过吗?掰开、撑直、再弯回去,你会发现它居然能弹回原来的形状,哪怕折腾个十几次依然不肯“投降”。就… · 2026/11/2 14:33:45
测试工程师如何争取N+10裁员补偿:谈判策略与筹码运用 1. 为什么软件测试工程师能争取N10? 在互联网行业裁员潮中,测试工程师往往处于相对被动的位置。但根据我过去5年协助30测试同行谈判的经验,这个岗位其实具备独特的谈判优势。测试工程师日常工作中积累的项目文档、测试用例、质量报告等材料&a… · 2026/11/2 17:06:53
Postgres MCP Pro 实战:数据库健康检查与性能分析 1. 为什么我盯上了 Postgres MCP Pro 这个工具数据库健康检查这件事,做过运维和后台开发的人都懂,平时没人惦记它,一旦出事就是半夜被电话叫醒的级别。我手里管着几套 PostgreSQL 实例,规模不大但杂事不少:连接数有没有… · 2026/11/2 17:06:53
TCP/IP网络模型与DDoS攻击防御实战解析 1. 网络通信模型基础解析 网络通信模型是理解现代网络架构的核心框架。OSI七层模型和TCP/IP四层模型是最常见的两种网络分层架构。在实际工作中,我更倾向于使用TCP/IP四层模型,因为它更贴近互联网的实际实现。 TCP/IP模型从下到上分为: 网络… · 2026/11/2 17:06:53
ICS安全新纪元:ATTCK v18框架深度解析与应用 1. 工业控制系统安全新纪元:ATT&CK v18框架深度解析当Stuxnet病毒在2010年首次震撼全球时,工业控制系统(ICS)安全还只是少数专家的专属领域。如今,随着关键基础设施数字化进程加速,MITRE ATT&CK v18框架专门针对ICS场景的… · 2026/11/2 17:06:53
Jev读出端:让大模型不开口也能做决策,Agent工具调用延迟降一个量级 1. 先聊聊“Jev 读出端”到底是个什么思路1.1 我为什么盯上这个方向最近在做 Agent 调度和工具调用相关的东西,发现一个特别扎眼的瓶颈:大模型每次做决策,都要先“说”一大段话,再在话里挑出工具名和参数,然后交给执行… · 2026/11/2 17:06:53
AI监管、算力与幽灵模型:三大事件如何重塑行业 今天的AI圈子,用“信息轰炸”来形容一点不过分。早上打开消息列表,联合国安理会那场讨论AI“限速”的听证会先占了半屏;中午云栖大会上真武V900正式亮相,朋友圈里瞬间刷起算力话题;晚上还没缓过神,Gemini 4… · 2026/11/2 17:05:48
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 4:42:45
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 5:17:18
雷达信号调制技术解析:从LFM到伪线性调频原理与应用 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 1:01:15
基于MAX14431与TM4C123的工业SPI隔离电路设计全攻略 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 1:01:15
PLFM_RADAR:相位线性调频雷达信号处理框架 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 1:01:15
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 4:42:45
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 5:17:18