Leeetcode每日一练--day1_数组

分析:

如果正向解答,每次减去数组最左边或者最右边的元素,来保证操作数为最优,再去判断x是否为0。某一次操作后,x的结果有三种可能,如果是等于0,那最好不过,因为一路都是选择较大值,所得操作数可以保证为最优解,如果是大于0,那就是无解,如果是小于0,这就麻烦了,需要回退到上一步重新选择,选择减去较小值,此时依然有三种情况,等于0不用说,皆大欢喜,如果大于0,那继续向后操作,如果是小于0,需要继续回退。也就是说,如果每次选择减去较大值,那么当x的值小于0时,需要回退,一旦回退的值仍然不满足条件,需要继续向后回退或者向后继续进行,而每次选择都有可能是另外两种不符合条件的情况。

而如果暴力尝试每一种组合,每一次选择都有两张情况,最左边或者最右边,一旦数组元素过多,组合数就相当于指数爆炸。

解题思路:抛开两边看中间,如果有解,无非就是数组中间的元素和为,数组元素总大小减去x,最优解就意味着,中间元素的个数要最多。也就是说,此时题目相当于是在数组中寻找值为数组元素和-x的最长子数组。而对于连续数组的求解,滑动窗口是最好的选择。

按照思路,提交代码后,出现报错。如下图

Leeetcode每日一练--day1_最优解_02

heap-buffer-overflow,堆数组越界,很明显,只有vector数组的数据是在堆上存储的,也就是vector数组出现越界访问。

开始寻找错误:

利用错误样例实验,在访问vector数组前的地方对数组下标进行打印。

Leeetcode每日一练--day1_数组元素_03

Leeetcode每日一练--day1_数组_04

不难看出越界错误是因为l在内循环中不断增加,最终越界导致的。加上对l的判断防止越界访问即可解决问题。

最终代码:

class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        int sum=0;
        for(auto e:nums)
        {
            sum+=e;
        }
        int target=sum-x;
        if(target<0)  retunr -1;//优化
        int maxlength=-1;
        int l=0,r=0;
        int sum1=0;
        while(l<nums.size()&&r<nums.size())
        {

            sum1+=nums[r];//进窗口
            while(l<nums.size()&&sum1>target)//防止l下标越界访问vector
            {
                sum1-=nums[l++];//出窗口
            }
            if(sum1==target)
            {
                maxlength=max(maxlength,r-l+1);//更新结果
            }

            r++;
        }

        return maxlength==-1?maxlength:(nums.size()-maxlength);

    }
};