剑指 Offer II 010. 和为 k 的子数组

剑指 Offer II 010. 和为 k 的子数组_第1张图片
思路:
(1)暴力法:时间复杂度o(n^3)
(2)优化后的暴力法:时间复杂度o(n^2)
(3)累加数组数字:时间复杂度o(n)

(1)暴力法
时间复杂度太高了,运行超时了。

class Solution {
public:
    int subarraySum(vector<int>& nums, int k)
    {
        int res = 0;
        for (int i = 0;i < nums.size();i++)
        {
            int sum = 0;
            sum += nums[i];
            if (sum == k)
                res++;
            for (int j = i + 1;j < nums.size();j++)
            {
                sum += nums[j];
                if (sum == k)
                {
                    res++;
                }

            }
        }
        return res;
    }
};

(3)累加数组和
    因为本题是求连续子数组,我们用前缀和去做,遍历一次数据,将前N个数字的和作为key保存在哈希表里面,如果有重复则value+1。
    当我们遍历的时候出现前N项和减去目标值在哈希表里面的时候,就表示有符合的子串,这里是最难以理解的地方。
    让哈希表的第一个键为(0,1)也很重要,这表示刚好我们遍历的第N个数的前N项和就是等于k的。

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int, int> ump;
        ump[0] = 1; // 表示以nums[i]结尾的序列和正好是k的情况
        int preSum = 0;
        int result = 0;
        for (int i = 0; i < nums.size(); i++) {
            preSum += nums[i];
            if (ump.count(preSum - k) != 0) { // 查找一下之前记录的前缀和中是否出现过preSum[i] - k,肯定是往前找 
                result += ump[preSum - k];
            }
            ump[preSum]++; // 不断更新哈希表中前缀和的情况
        }
        return result;
    }
};

你可能感兴趣的:(算法,leetcode,c++)