將x減到0的最小操作數
- 個人總結的八步歸納
- AI的歸納
- **8步歸納法(極簡直白版)**
- 1. 問題本質
- 2. 問題特征
- 3. 切入點
- 4. 解決流程
- 5. 每步目標與操作
- 6. 注意事項
- 7. 最終目標
- 8. 整體總結
- 代碼對照(逐行解析)
- 舉個栗子🌰
- **一句話總結**
題目鏈接:
將x減到0的最小操作數
題目描述:
給你一個整數數組 nums 和一個整數 x 。每一次操作時,你應當移除數組 nums 最左邊或最右邊的元素,然后從 x 中減去該元素的值。請注意,需要 修改 數組以供接下來的操作使用。
如果可以將 x 恰好 減到 0 ,返回 最小操作數 ;否則,返回 -1 。
示例 1:
輸入:nums = [1,1,4,2,3], x = 5
輸出:2
解釋:最佳解決方案是移除后兩個元素,將 x 減到 0 。
示例 2:
輸入:nums = [5,6,7,8,9], x = 4
輸出:-1
示例 3:
輸入:nums = [3,2,20,1,1,3], x = 10
輸出:5
解釋:最佳解決方案是移除后三個元素和前兩個元素(總共 5 次操作),將 x 減到 0 。
提示:
1 <= nums.length <= 105
1 <= nums[i] <= 104
1 <= x <= 109
題目轉化:
這個題目的要求是求出數組左右兩邊相加等于x的最短長度的和
也就是:
找出最長的子數組的長度
這個子數組的所有元素的和正好等于sum - x
sum是整個數組的所有元素的和
和之前討論過的滑動窗口一模一樣:
我們這里就直接使用滑動窗口來解決這道題目:
個人總結的八步歸納
第一步:用自己的話,描述一下眼前的這個問題,它是一個怎么樣的問題?
要求的是數組左右兩邊的和等于X的最小長度
第二步:這個問題有哪些特征,能讓我們去判斷,它屬于這一類的問題?
正難則反,可以涉及到連續的長度子數組,以及求最短,最長的長度,這道題目就可以轉換為求出一個子數組,要求在這個連續的子數組的和是等于 總數組的和減去x的,最后返回總數組的長度減去子數組的長度,如果這個子數組的和不能等于sum-x,那么就返回-1。
第三步:想要解決這類問題,切入點啥,即第一步我們要從哪里開始?
切入在在于轉化為求一個連續子數組的最長的長度,這個子數組的和等于sum-x
第四步:解決這個問題的流程是怎么樣的?這里說的流程是指,這道題可以分成12345…步,只要按照12345這個順序做下去,我們就能解決這個問題。
- 定義一個ret變量,初始化為-1,記錄子數組的最長長度
- 定義一個sum記錄總數組的和,n記錄總數組的長度
- 定義一個target記錄sum - x,如果這個target小于0,那返回-1
- 定義一個temp記錄這個子數組的和
- 使用同向雙指針去擴展temp的右窗口
- 如果temp 的值大于了target,那就左縮窗口
- 如果temp 剛好等于target,那就更新re的結果為最大的長度
- 最后,如果ret= -1,說明沒有這個連續子數組沒有剛好等于target的值,那么就返回-1
- 如果ret不是等于-1,那么就返回n - ret
第五步:在流程的12345步中,每一步的目標是什么(就是要求到些什么)?每一步需要用到哪些知識
- ret為了記錄子數組的最長長度
- sum 記錄總數組長度的值
- target記錄sum -x的值
- temp記錄子數組的元素總和
- 開始使用滑動窗口去擴展temp的值
- 當temp的值大于target時,就要左縮窗口,當temp=target時,更新ret的結果
- 如果ret=-1,那就說明沒有子數組的和正好等于sum-x
- 如果ret !=-1;那就說明有子數組的和剛好等于了sum-x
- 最后我們就返回n-ret即可
第六步:要思考在運用這些知識和技巧的時候,有些需要注意的地方。
- 記錄target時,如果sum - x < 0了,那就直接返回了-1
- 使用的是temp來記錄子數組的和,來帶入滑動窗口中計算
- 當temp == target的時候,才會去更新結果
- 最后要返回的是-1或者是n-ret
第七步:要解決這個問題,最終的目標是啥?也就是說,我最終要求出的是啥?
最終目標是求出這個總數組中左右子數組的和正好等于x的最小長度
我們將這個目標轉換為了:
求出這個總數組中的一個連續的子數組的和正好等于sum-x的最長長度
第八步:重新對上面的第一步至第七步,進行回顧和揣摩(包括問題類型,特征,切入點,解決過程,1234567…步,每步需要用的哪些知識方法)
(2)AI+8步歸納結合
在模仿完題目后,先自己用8步歸納法對錯題進行歸納,然后讓deepseek,按照8步歸納法的原則,對題目進行總結歸納,你再把自己總結歸納出的東西,跟AI對比,看看有哪些地方可以改進。
AI的歸納
8步歸納法(極簡直白版)
1. 問題本質
從數組兩端不斷刪除元素,使刪除的元素和等于x,求最少刪幾次?若做不到,返回-1。
2. 問題特征
- 逆向思維:求兩端刪除次數最少 → 等價于求中間保留的連續子數組最長
- 數學轉化:中間子數組的和 = 總和 - x
- 滑動窗口適用:數組元素全為正數,適合用雙指針找連續子數組
3. 切入點
- 算數組總和
sum
- 算目標值
target = sum - x
- 若
target < 0
:直接返回-1(總和都不夠x)
- 若
- 用滑動窗口找和為
target
的最長子數組
4. 解決流程
- 算總和:遍歷數組求
sum
- 算目標:
target = sum - x
,若target < 0
返回-1 - 滑動窗口:
- 雙指針
left=0
,currentSum=0
right
右移累加元素 →currentSum += nums[right]
- 當
currentSum > target
時,左移left
減元素 →currentSum -= nums[left++]
- 當
currentSum == target
時,記錄窗口長度right-left+1
的最大值
- 雙指針
- 結果處理:
- 若未找到 → 返回-1
- 若找到 → 最少操作次數 = 數組長度 - 最長子數組長度
5. 每步目標與操作
步驟 | 做什么 | 為什么這么做 |
---|---|---|
算總和 | 確定中間子數組的目標和 | 轉化問題核心條件 |
滑動窗口 | 找和為target 的最長子數組 | 滑動窗口能高效處理連續子數組問題 |
結果轉換 | 將子數組長度轉為操作次數 | 原問題要求的是兩端的操作次數 |
6. 注意事項
- 邊界情況1:若
target = 0
(即sum = x
),需刪除整個數組 → 返回n
- 邊界情況2:數組全為1,x=5,但總和=3 → 直接返回-1
- 效率:每個元素最多被訪問兩次 → 時間復雜度O(n)
7. 最終目標
求最少刪除次數 = 數組長度 - 中間最長子數組的長度
8. 整體總結
- 問題轉化:刪除兩端 → 保留中間最長
- 核心操作:滑動窗口找和為
target
的最長子數組 - 代碼框架:
計算總和 → 處理邊界 → 滑動窗口找最長子數組 → 返回結果
代碼對照(逐行解析)
class Solution {public int minOperations(int[] nums, int x) {int sum = 0;for (int num : nums) sum += num; // 1. 算總和int target = sum - x; // 2. 算目標值if (target < 0) return -1; // 邊界:總和都不夠xint maxLen = -1; // 記錄中間最長子數組的長度int left = 0, currentSum = 0;// 3. 滑動窗口找最長子數組for (int right = 0; right < nums.length; right++) {currentSum += nums[right]; // 右指針擴張while (currentSum > target) // 窗口和太大,左指針收縮currentSum -= nums[left++];if (currentSum == target) // 找到合法窗口maxLen = Math.max(maxLen, right - left + 1);}// 4. 結果處理return maxLen == -1 ? -1 : nums.length - maxLen;}
}
舉個栗子🌰
以示例1 nums = [1,1,4,2,3], x = 5
:
sum = 11
→target = 11-5 = 6
- 找和為6的最長子數組:
[1,1,4]
和=6 → 長度3- 或
[4,2]
和=6 → 長度2 - 最長長度為3
- 最少操作次數 = 5(總長) - 3 = 2
一句話總結
求兩端刪最少 → 中間留最長 → 滑動窗口找和為sum-x
的最長子數組