返回

从Offer敲门到掘金打卡:挑战2104. 子数组范围和题海漫漫,勇者无畏

后端

【刷题日记】2104. 子数组范围和

踏上春招的征途,我决定拾起许久没有进行的刷题习惯,而2104. 子数组范围和则是我的第一站。

题目

给你一个整数数组nums,和一个查询数组queries,其中queries[i]是[start_i, end_i]。

对于每个查询,返回数组nums中在范围[start_i, end_i]中的元素的总和。

示例 1:

输入:nums = [1,2,3,4,5], queries = [[1,3],[0,1],[2,4],[2,4],[3,4]]

输出:[9,3,15,15,11]

解释:

nums[1] + nums[2] + nums[3] = 9
nums[0] + nums[1] = 3
nums[2] + nums[3] + nums[4] = 15
nums[2] + nums[3] + nums[4] = 15
nums[3] + nums[4] = 11

示例 2:

输入:nums = [10,5,-2,-3,7,5,5,2,1], queries = [[0,4],[1,2],[0,7],[3,7],[3,7],[2,6]]

输出:[23,-3,18,18,18,17]

解释:

nums[0] + nums[1] + nums[2] + nums[3] + nums[4] = 23
nums[1] + nums[2] = -3
nums[0] + nums[1] + nums[2] + nums[3] + nums[4] + nums[5] + nums[6] + nums[7] + nums[8] = 18
nums[3] + nums[4] + nums[5] + nums[6] + nums[7] = 18
nums[3] + nums[4] + nums[5] + nums[6] + nums[7] = 18
nums[2] + nums[3] + nums[4] + nums[5] + nums[6] = 17

解题思路

对于给定的查询数组,我们可以计算每个查询的范围和,然后将结果存储在数组中。在计算范围和时,我们可以使用动态规划来优化性能。

动态规划算法

我们首先定义一个状态数组dp,其中dp[i]表示nums数组中以索引i结尾的子数组的和。然后,我们使用以下递推公式来计算dp数组:

dp[i] = dp[i-1] + nums[i]

一旦我们计算了dp数组,我们就可以通过以下方式计算每个查询的范围和:

query_sum = dp[end_i] - dp[start_i-1]

Java代码

class Solution {
    public int[] subarraySumQueries(int[] nums, int[][] queries) {
        int[] dp = new int[nums.length+1];
        for (int i = 1; i < dp.length; i++) {
            dp[i] = dp[i-1] + nums[i-1];
        }

        int[] result = new int[queries.length];
        for (int i = 0; i < queries.length; i++) {
            int start = queries[i][0];
            int end = queries[i][1];
            result[i] = dp[end+1] - dp[start];
        }

        return result;
    }
}

Python代码

def subarraySumQueries(nums, queries):
    dp = [0] * (len(nums)+1)
    for i in range(1, len(dp)):
        dp[i] = dp[i-1] + nums[i-1]

    result = []
    for query in queries:
        start = query[0]
        end = query[1]
        result.append(dp[end+1] - dp[start])

    return result

C++代码

class Solution {
public:
    vector<int> subarraySumQueries(vector<int>& nums, vector<vector<int>>& queries) {
        vector<int> dp(nums.size()+1, 0);
        for (int i = 1; i < dp.size(); i++) {
            dp[i] = dp[i-1] + nums[i-1];
        }

        vector<int> result;
        for (auto& query : queries) {
            int start = query[0];
            int end = query[1];
            result.push_back(dp[end+1] - dp[start]);
        }

        return result;
    }
};

总结

通过这道题,我复习了动态规划的思想和算法,并将其应用到了实际的问题中。在解决问题的过程中,我遇到了几个难点:

  • 如何定义状态数组dp。
  • 如何使用递推公式来计算dp数组。
  • 如何使用dp数组来计算每个查询的范围和。

通过反复思考和查阅资料,我最终解决了这些问题,并得到了正确的答案。这让我对动态规划有了更深入的理解,也对自己的编程能力有了更多的信心。

在未来的刷题过程中,我会继续努力,争取取得更好的成绩。我相信,只要坚持不懈,终能有所收获。