零数组变换I

题目描述

题目描述

题目意思,即二维数组queries的每个元素表示每次要处理的nums数组的下标子集,如果处理完之后,可将nums变为零数组,返回true。

算法思路

每次要处理某个下标范围(或者子集)的内nums数组,看其能否全变为0,那么我们每次都处理[l,r]范围内的数据,将其-1,这种情况一定是能让nums数组中元素变为最小值的。因此,如果该情况都不能够让所有nums的元素小于等于0,那么就不可以变为零数组。

代码实现

class Solution {
    public boolean isZeroArray(int[] nums, int[][] queries) {
        boolean ans=true;
        for(int i=0;i<queries.length;i++){
            int l=queries[i][0],r=queries[i][1];
            for(int j=l;j<=r;j++){
                if(nums[j]>0) nums[j]--;
            }
        }
        for(int i=0;i<nums.length;i++){
            if(nums[i]!=0){
                ans=false;
                break;
            }
        }
        return ans;
    }
}

最坏情况下,每个查询需要O(n)的时间(n是数组长度),m个查询的总时间是O(mn),如果m和n都很大,会超时。
超时的情况

优化算法

使用差分数组来记录区间操作,最后统计每个位置被减了多少次。
1.差分数组diff:
diff[i]表示nums[i]比nums[i-1]多减了几次。
对区间[l,r]上的减法,可以转化为:diff[l]--(表示从l开始减1),diff[r+1]++(表示在r+1处取消减1)
2.计算最终减的次数:
遍历diff数组,累加差分值,得到每个位置nums[i]都被减了多少次(即为detail[i]),如果nums[i]-detail[i]>0,说明无法减到0,返回false。

代码实现

class Solution {
    public boolean isZeroArray(int[] nums, int[][] queries) {
        int n = nums.length;
        int[] diff = new int[n + 1]; // 差分数组

        // 处理所有查询
        for (int[] q : queries) {
            int l = q[0], r = q[1];
            diff[l]--;
            if (r + 1 < n) diff[r + 1]++;
        }

        // 计算每个位置的 delta(总共减了多少次)
        int delta = 0;
        for (int i = 0; i < n; i++) {
            delta += diff[i];
            if (nums[i] + delta > 0) { // nums[i] - (-delta) > 0
                return false;
            }
        }
        return true;
    }
}

此时的时间复杂度为O(m+n),m是查询数,n是数组长度。
空间复杂度为O(n),n为差分数组所占空间。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容