240
笔下虽有千言,胸中实无一策

30 Day Challenge Day 1 | Hackerrank - Array Manipulation

题述

原题见链接

题解

根据题意,很容易想到蛮力解法如下:

Brute Force Method

// Complete the arrayManipulation function below.
long arrayManipulation(int n, vector<vector<int>> queries) {
    vector<long> arr(n, 0);
    long max_val = 0;
    for(auto q : queries) {
        int l = q[0]-1, r = q[1]-1;
        for(int i = l; i <= r; ++i) {
            arr[i] += q[2];
            if(max_val < arr[i]) {
                max_val = arr[i];
            }
        }
    }
    return max_val;
}

这道题难度级别是Hard,可想而知,应该没有那么简单。提交以后没有通过所有测试用例,原因是超时。

蛮力解法的复杂度是\(O(n^2)\)。有没有办法降低复杂度呢?

讨论版提示了一种方法,避免把区间内的所有元素都操作一遍,毕竟这里有一个特点是,每次区间内的元素都是加上同样的值。不妨只操作一次。

对上面的代码做一点修改,找到区间的开始点\(l\)和结束点\(r\)以后,只在开始位置\(l\)加上对应值,在区间结束点的下一位(如果存在的话)减去这个对应值。

        arr[l] += q[2];
        if(r+1 < n) arr[r+1] -= q[2];

这样一来,最后得到的数组通过区间求和操作得到最大指。这个方法叫做Prefix Sum Algorithm,还是第一次了解到。

举例来说,如果输入如下:

5 3
1 2 100
2 5 100
3 4 100

那么操作过程如下:

Original: 0 0 0 0 0
Step 1: 100 0 -100 0 0
Step 2: 100 100 -100 0 0
Step 3: 100 100 0 0 -100

那么,子区间\([0,i](i<=n)\)内求和得到的最大值是200,也就是所要求的结果。

最终通过的题解如下:

Prefix Sum Algorithm

// Complete the arrayManipulation function below.
long arrayManipulation(int n, vector<vector<int>> queries) {
    vector<long> arr(n, 0);
    long max_val = 0;

    for(auto q : queries) {
        int l = q[0]-1, r = q[1]-1;
        arr[l] += q[2];
        if(r+1 < n) arr[r+1] -= q[2];
    }

    long sum = 0;
    for(int i = 0; i < n; i++) {
       sum = sum + arr[i];
       if(max_val < sum) max_val = sum;
    }

    return max_val;
}
posted @ 2020-07-03 04:10  CasperWin  阅读(255)  评论(0编辑  收藏  举报