ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

LeetCode 1658 最小操作数减 X 到零:Go 实现滑动窗口逆向思维全解析

LeetCode 1658 最小操作数减 X 到零:Go 实现滑动窗口逆向思维全解析 LeetCode 1658 最小操作数减 X 到零Go 实现滑动窗口逆向思维全解析【免费下载链接】LeetCode-Go✅ Solutions to LeetCode by Go, 100% test coverage, runtime beats 100% | LeetCode 题解项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Go导读LeetCode 1658 是一道经典的两端取数问题每次操作只能从数组最左端或最右端移除一个元素并从x中减去其值求恰好将x减到 0 所需的最小操作数。本文以 LeetCode-Go 仓库中 1658.Minimum-Operations-to-Reduce-X-to-Zero 的官方题解为骨架完整还原其核心解题思路——把两端的数字最少逆向转化为中间连续子数组最长并给出可直接运行的 Go 源码、测试用例与复杂度分析。读完本文你将掌握这类两端操作问题通用的滑动窗口转化技巧。题目理解给定一个整数数组nums和一个整数x每一次操作时应移除数组nums最左边或最右边的元素然后从x中减去该元素的值并且需要修改数组以供接下来的操作使用。如果可以将x恰好减到 0返回最小操作数否则返回-1。原文档给出了三个示例示例 1 Input: nums [1,1,4,2,3], x 5 Output: 2 解释最优解是移除最后两个元素即可把 x 减到 0。 示例 2 Input: nums [5,6,7,8,9], x 4 Output: -1 示例 3 Input: nums [3,2,20,1,1,3], x 10 Output: 5 解释最优解是移除最后三个元素和前两个元素共 5 次操作即可把 x 减到 0。数据约束原文档 Constraints1 nums.length 10^51 nums[i] 10^41 x 10^9题目大意是从数组两端分别移除一些数使得这些被移除的数加起来正好等于整数x要求输出最小操作数否则返回-1。核心思路逆向转化为最长连续子数组这是本题最关键的一步思维转换也是原文档解题思路的核心要求输出最小操作数即数组两头的数字个数最少并且加起来和正好等于x。由于要操作的位置在数组的两头直接用 2 个指针分别操作不太方便。原文档作者当时解题时的思路是把它变成循环数组这样两边的指针就在一个区间内了再利用滑动窗口找一个最小的窗口使得窗口内累加和等于整数x。这个方法可行但代码较多。更优美的做法要想两头的长度最少也就是中间这段的长度最大。这样就转换成直接在数组上使用滑动窗口求解寻找累加和等于一个固定值的连续最长子数组。具体而言令数组总和为total那么中间连续子数组的目标和为target total - x若target 0说明数组总和都小于x无论怎么移除都无法减到 0直接返回-1若target 0说明必须把整个数组全部移除操作数就是len(nums)否则用滑动窗口在nums上寻找和为target的最长连续子数组其长度为res答案即为len(nums) - res。这个逆向转化把从两端取数这种不便于双指针直接处理的场景规约成了经典的定和最长子数组问题时间复杂度由可能的指数级搜索降为一次线性扫描。边界情况分析在动手写代码前先梳理清楚三类边界情况total x数组内所有元素之和都小于x两端移除不可能凑出x答案是-1。total x需要把整个数组全部移除操作数为nn为数组长度。存在恰好等于target的子数组找到其中最长的那个答案取n - 最长长度若找不到任何和为target的连续子数组则答案同样为-1。这些边界分支在仓库源码 1658. Minimum Operations to Reduce X to Zero.go 的前半部分均有显式处理。Go 源码实现逐行解析仓库中的完整实现如下与 README.md 中给出的代码一致package leetcode func minOperations(nums []int, x int) int { total : 0 for _, n : range nums { total n } target : total - x if target 0 { return -1 } if target 0 { return len(nums) } left, right, sum, res : 0, 0, 0, -1 for right len(nums) { if sum target { sum nums[right] right } for sum target { if sum target { res max(res, right-left) } sum - nums[left] left } } if res -1 { return -1 } return len(nums) - res } func max(a, b int) int { if a b { return a } return b }关键步骤说明第 3-7 行先遍历一遍数组求出总和total得到中间子数组的目标和target total - x。第 8-13 行处理两类边界情况——target 0直接返回-1target 0返回len(nums)。第 15 行初始化滑动窗口。left、right为窗口左右边界左闭右开sum维护窗口内元素和res记录和为target的最长窗口长度初始为-1表示尚未找到。第 16-19 行当sum target时右指针right向右扩张把新元素纳入窗口。第 20-26 行当sum target时进入内层循环若sum target则用max(res, right-left)更新最长长度随后把左指针元素移出窗口sum - nums[left]; left继续收缩寻找更优解。第 28-32 行若始终没有找到和为target的窗口res -1返回-1否则返回len(nums) - res即需要移除的元素个数。注意res max(res, right-left)中right-left恰好是当前窗口长度因为right已指向窗口右开边界这也解释了为何源码在sum target时直接以right-left参与比较。复杂度分析时间复杂度O(n)。数组只被完整遍历一次用于求和滑动窗口的左右指针各至多移动n次整体线性。空间复杂度O(1)。仅使用若干整型变量没有额外数组或哈希表。该解法可以在一次线性扫描内同时完成找定和窗口与求最长长度两个目标相比构造循环数组 双指针的朴素做法代码量更少、边界更清晰。测试用例与验证仓库配套的测试文件 1658. Minimum Operations to Reduce X to Zero_test.go 使用表格驱动table-driven风格组织用例完整覆盖了以下场景numsx期望输出覆盖点[1,1,4,2,3]52原题示例 1只移除右侧两个元素[5,6,7,8,9]4-1原题示例 2无法凑出目标值[3,2,20,1,1,3]105原题示例 3左右两侧都要移除[1,1]5-1total x的边界分支[1,2,3]63total x需移除全部元素其中最后两个用例对应本文前面分析的边界分支[1,1]总和为 2 小于x5直接命中target 0返回-1[1,2,3]总和恰好等于x6命中target 0返回len(nums) 3。测试通过got ! a.one判定失败并打印input/output可以在仓库根目录执行go test ./leetcode/1658.Minimum-Operations-to-Reduce-X-to-Zero/ -v复现运行结果。解法思路的延伸同类题推荐原文档在解题思路末尾明确给出了与本题思路相似的三道推荐题目209. Minimum Size Subarray Sum同样是滑动窗口求解连续子数组和问题不过本题求的是和≥ s的最短连续子数组与 1658 的定和最长恰好互为镜像。本仓库已有完整实现参见 209.Minimum-Size-Subarray-Sum1040. Moving Stones Until Consecutive II涉及循环数组与端点移动限制的思维题其最小步数求解同样借助了定长滑动窗口参见 1040.Moving-Stones-Until-Consecutive-II325. Maximum Size Subarray Sum Equals k与 1658 的逆向转化几乎同构——求和为固定值的最长连续子数组区别在于 325 允许负数需借助哈希表维护前缀和而 1658 因数组全为正数可直接用滑动窗口本题在 LeetCode 上需要付费订阅查看。从源码结构可以推断本仓库将 209 与 1040 的题解含_test.go测试文件以同样的目录规范组织便于横向对比学习这三道题在滑动窗口运用上的异同。总结LeetCode 1658 的精髓在于逆向思维与其直接模拟从两端移除元素的过程不如把问题等价地改写为找到和为total - x的最长连续子数组再用一次线性滑动窗口求解。本仓库的 Go 实现仅用约 30 行代码即完成全部逻辑并通过表格驱动测试覆盖了原题示例与边界分支。掌握这一转化模式后无论是本题还是 209、1040、325 等同类滑动窗口题目都可以举一反三、快速定位解法。【免费下载链接】LeetCode-Go✅ Solutions to LeetCode by Go, 100% test coverage, runtime beats 100% | LeetCode 题解项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Go创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表