TEST(TestCase, Case1) { auto s = Solution(); auto nums = vector<int>{1, 1, 1}; auto actual = s.subarraySum(nums, 2); auto expected = 2; EXPECT_EQ(expected, actual); } TEST(TestCase, Case2) { auto s = Solution(); auto nums = vector<int>{1, 2, 3}; auto actual = s.subarraySum(nums, 3); auto expected = 2; EXPECT_EQ(expected, actual); } TEST(TestCase, Case3) { auto s = Solution(); auto nums = vector<int>{1, 2, 1, 2, 4, -1}; auto actual = s.subarraySum(nums, 3); auto expected = 4; EXPECT_EQ(expected, actual); }
解き方
累積和を使います。nums の先頭から見ていって総和を求めます。総和 - k の値が過去に現れていたら和が k となるような部分配列があることを示しています。
以下は nums = [1,2,3], k = 3 の例です。nums 配列の添え字を i 、総和を sum とします。
classSolution { public: intsubarraySum(vector<int> &nums, int k) { int n = nums.size(); int sum = 0; unordered_map<int, int> sum_to_count; sum_to_count[0] = 1; int answer = 0; for (int i = 0; i < n; i++) { sum += nums[i]; answer += sum_to_count[sum - k]; sum_to_count[sum]++; } return answer; } };