1.題目描述
2.題目鏈接?
1658. 將 x 減到 0 的最小操作數 - 力扣(LeetCode)
3.題目分析
1)正面求解困難
?題目要求我們每次都從最左邊或者最右邊取一個數,使x-元素的值,并在數組中移除該元素。最后返回的最小操作數也就是移除數組元素的最小個數。
也就是如下:
其中a和b代表對應子串的元素和。
這道題如果我們從正面求解,是非常困難的。因為他有可能是從最左邊移除,也有可能從最右邊移除,并且要求a+b=x,還要求最小值,情況是非常多的。
2)正難則反
既然正面求解困難,那么我們反過來換一種思路,從反面求解,也就是求和為sum-x的子串的最長長度:
其中sum表示數組所有元素和。
這就和我們前面做過的一道滑動窗口的oj題目非常相似了:?力扣-長度最小的子數組-CSDN博客。
4.代碼解答
class Solution {public int minOperations(int[] nums, int x) {int length=-1,sum=0,temp=0;for(int a:nums)sum+=a;int target=sum-x;if(target<0){return -1;}for(int left=0,right=0;right<nums.length;right++){temp+=nums[right];while(temp>target&&left<=right){temp-=nums[left++];}if(temp==target){length=Math.max(length,right-left+1);}}return length==-1?-1:nums.length-length;}
}
5.代碼細節
1)length的初始值
int length=-1,sum=0,temp=0;
題目中要求如果沒有找到符合條件的字串,就返回-1,所以我們通過定義length的初始值為-1,在結合三位運算符進行返回:
return length==-1?-1:nums.length-length;
2)while循環的條件
while(temp>target&&left<=right){temp-=nums[left++];}
應該是left<=right而不是left<=right,確保窗口可以收縮到空(left > right),從而正確處理所有邊界情況。這時中間的子串為空,也就是說,此時整個數組的元素和是題目中給出的x,要返回的就是整個數組的長度。
這是滑動窗口算法中常見的邊界陷阱,需要特別注意!