Web Development/algorithm

[Algorithm][LeetCode 560] Subarray Sum Equals K ๋ฌธ์ œ ํ’€์ด - ๋ˆ„์ ํ•ฉ๊ณผ Hash Map ํ™œ์šฉ๋ฒ•

devflate 2025. 4. 27. 15:36

๐ŸŸข LeetCode 560. Subarray Sum Equals K ๋ฌธ์ œ ํ’€์ด (with ๋ˆ„์ ํ•ฉ + ํ•ด์‹œ๋งต)

์ตœ๊ทผ Leetcode 2845. Count of Interesting Subarrays ๋ฌธ์ œ๋ฅผ ํ’€๋‹ค๊ฐ€ ๋ง‰ํžˆ๋Š” ๋ถ€๋ถ„์ด ์žˆ์—ˆ๋Š”๋ฐ, ์œ ํŠœ๋ธŒ์—์„œ ํžŒํŠธ๋ฅผ ์ฐพ์•„๋ณด๋‹ค๊ฐ€ ์•„๋ž˜ ์˜์ƒ์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค.

How to solve Count of Interesting Subarrays (Leetcode 2845)

์ด ์˜์ƒ์—์„œ๋Š” Leetcode 560๋ฒˆ๊ณผ 523๋ฒˆ ๋ฌธ์ œ๋ฅผ ๋จผ์ € ํ’€์–ด๋ณด๋ฉด ์ดํ•ด๊ฐ€ ์ž˜ ๋œ๋‹ค๊ณ  ์ถ”์ฒœํ•˜๋”๋ผ๊ณ ์š”.
๊ทธ๋ž˜์„œ ๋จผ์ € Leetcode 560. Subarray Sum Equals K ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.


๐ŸŸข ๋ฌธ์ œ ์„ค๋ช…

Given an array of integers nums and an integer k,
return the total number of subarrays whose sum equals to k.

  • Subarray: ์—ฐ์†๋œ ์š”์†Œ๋“ค์˜ ๋ถ€๋ถ„ ๋ฐฐ์—ด (๋น„์–ด ์žˆ์œผ๋ฉด ์•ˆ ๋จ).
  • Example 1:
    Input: nums = [1,1,1], k = 2
    Output: 2
    
  • Example 2:
    Input: nums = [1,2,3], k = 3
    Output: 2
    
  • Constraints:
    1 <= nums.length <= 2 * 10โด
    -1000 <= nums[i] <= 1000
    -10โท <= k <= 10โท
    

๐ŸŸ  ์ ‘๊ทผ ๋ฐฉ๋ฒ• (์ด 3๊ฐ€์ง€)

1๏ธโƒฃ Brute Force ๋ฐฉ์‹ (O(N²), O(1))

๊ฐ€์žฅ ์ง๊ด€์ ์ธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
๋ชจ๋“  subarray๋ฅผ ํ•˜๋‚˜ํ•˜๋‚˜ ํ™•์ธํ•˜๋ฉด์„œ ํ•ฉ์ด k์ธ ๊ฒฝ์šฐ๋ฅผ ์„ธ๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

const subarraySum = function(nums, k) {
    let count = 0;
    for (let i = 0; i < nums.length; i++) {
        let sum = 0;
        for (let j = i; j < nums.length; j++) {
            sum += nums[j];
            if (sum === k) count++;
        }
    }
    return count;
}
  • ์‹œ๊ฐ„ ๋ณต์žก๋„: O(N²)
  • ๊ณต๊ฐ„ ๋ณต์žก๋„: O(1)

โŒ ๋ฐฐ์—ด์ด ๊ธธ์–ด์งˆ์ˆ˜๋ก ๋งค์šฐ ๋А๋ ค์ง‘๋‹ˆ๋‹ค.


2๏ธโƒฃ Prefix Sum + 2์ค‘ ๋ฃจํ”„ (O(N²), O(N))

๋ˆ„์ ํ•ฉ(Prefix Sum)์„ ๋จผ์ € ๊ณ„์‚ฐํ•ด๋‘๊ณ ,
๊ตฌ๊ฐ„ํ•ฉ์„ prefixSum[i] - prefixSum[j]๋กœ ๊ตฌํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

const subarraySum = function(nums, k) {
    let prefix = 0;
    let count = 0;

    const preCalculatedSum = nums.map((num) => {
        prefix += num;
        return prefix;
    });

    for (let i = 0; i < preCalculatedSum.length; i++) {
        if (preCalculatedSum[i] === k) {
            count++;
        }
        for (let j = 0; j < i; j++) {
            if (preCalculatedSum[i] - preCalculatedSum[j] === k) {
                count++;
            }
        }
    }

    return count;
};
  • ์‹œ๊ฐ„ ๋ณต์žก๋„: O(N²)
  • ๊ณต๊ฐ„ ๋ณต์žก๋„: O(N)

โš ๏ธ Brute Force๋ณด๋‹ค๋Š” ์ค‘๋ณต ๊ณ„์‚ฐ์ด ์ค„์—ˆ์ง€๋งŒ, ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค.


3๏ธโƒฃ Prefix Sum + Hash Map (O(N), O(N)) โญ๏ธ

์ด ๋ฌธ์ œ์˜ ์ตœ์ ํ™”๋œ ์ ‘๊ทผ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

โœ… ํ•ต์‹ฌ ์•„์ด๋””์–ด
  • ๊ตฌ๊ฐ„ํ•ฉ์€ ๋ˆ„์ ํ•ฉ์˜ ์ฐจ์ด๋กœ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ตฌ๊ฐ„ [i, j]์˜ ํ•ฉ = prefixSum[j] - prefixSum[i - 1]
  • ์ด ๊ณต์‹์„ ๋ณ€ํ˜•ํ•˜๋ฉด:
    prefixSum[j] - k = prefixSum[i - 1]
    
  • ํ˜„์žฌ๊นŒ์ง€ ๋ˆ„์ ํ•ฉ์ด prefixSum[j]์ธ๋ฐ,
    ๊ณผ๊ฑฐ์— prefixSum[i - 1]์ด๋ผ๋Š” ๋ˆ„์ ํ•ฉ์ด ์žˆ์—ˆ๋‹ค๋ฉด, ๊ทธ ๊ตฌ๊ฐ„ํ•ฉ์€ k๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
  • ์ด์ „ ๋ˆ„์ ํ•ฉ์„ Hash Map์— ์ €์žฅํ•ด๋‘๊ณ ,
    ๋งค ์ˆœ๊ฐ„ prefixSum[j] - k๊ฐ€ ๊ณผ๊ฑฐ์— ์žˆ์—ˆ๋Š”์ง€ ๋น ๋ฅด๊ฒŒ ํ™•์ธํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
๐ŸŸก prefixSum[-1] = 0์„ 1๋กœ ๊ฐ€์ •ํ•˜๋Š” ์ด์œ 
  • ์•„๋ฌด ์ˆซ์ž๋„ ๊ณ ๋ฅด์ง€ ์•Š๊ณ  ๋”ํ•˜์ง€ ์•Š์€ ์ƒํƒœ๋ฅผ prefixSum[-1] = 0์ด๋ผ๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ˆ์‹œ: nums = [1, -1, 0], k = 0
  • ํ•ฉ์ด 0์ด ๋˜๋Š” subarray:
    1. [1, -1]
    2. [1, -1, 0]
    3. [0]
  • ์ด์ฒ˜๋Ÿผ ๋งจ ์•ž์—์„œ ์‹œ์ž‘ํ•˜๋Š” ๊ตฌ๊ฐ„์„ ๊ตฌํ•˜๋ ค๋ฉด,
    prefixSum[-1] = 0์ด๋ผ๋Š” ์ง€์ ์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ทธ๋ž˜์„œ ์ดˆ๊ธฐ ์„ค์ •์œผ๋กœ map.set(0, 1)์„ ํ•ด์ค๋‹ˆ๋‹ค.
๐ŸŸข ์ฝ”๋“œ
const subarraySum = function(nums, k) {
    const map = new Map();
    map.set(0, 1); // prefixSum[-1] = 0์„ 1๋ฒˆ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •

    let sum = 0;
    let count = 0;

    for (let num of nums) {
        sum += num;
        const target = sum - k;
        if (map.has(target)) {
            count += map.get(target); // ์ด์ „์— ๋‚˜์™”๋˜ target๋งŒํผ count ์ฆ๊ฐ€
        }
        map.set(sum, (map.get(sum) || 0) + 1); // ํ˜„์žฌ prefix sum ์ €์žฅ
    }

    return count;
};
  • ์‹œ๊ฐ„ ๋ณต์žก๋„: O(N)
  • ๊ณต๊ฐ„ ๋ณต์žก๋„: O(N)

โœ… ๋ˆ„์ ํ•ฉ์„ ์ด์šฉํ•˜๋ฉด์„œ, ๊ณผ๊ฑฐ ๋ˆ„์ ํ•ฉ์„ Map์œผ๋กœ ๊ด€๋ฆฌํ•ด์„œ ๋น ๋ฅด๊ฒŒ ๊ตฌ๊ฐ„ํ•ฉ์„ ์ฐพ๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.


๐ŸŸ  ์ •๋ฆฌ

๋ฐฉ๋ฒ• ์‹œ๊ฐ„ ๋ณต์žก๋„ ๊ณต๊ฐ„ ๋ณต์žก๋„ ํŠน์ง•
Brute Force O(N²) O(1) ๋‹จ์ˆœํ•˜๊ณ  ์ง๊ด€์ ์ด์ง€๋งŒ ๋А๋ฆผ
Prefix Sum + 2์ค‘ ๋ฃจํ”„ O(N²) O(N) ๋ˆ„์ ํ•ฉ ์‚ฌ์šฉ, ์ค‘๋ณต ๊ณ„์‚ฐ ์ผ๋ถ€ ๊ฐ์†Œ
Prefix Sum + Hash Map (์ถ”์ฒœ) O(N) O(N) ์ตœ์ ํ™”๋œ ๋ฐฉ์‹, ์‹ค๋ฌด์—์„œ๋„ ์ž์ฃผ ์‚ฌ์šฉ

๐Ÿงญ ๋งˆ๋ฌด๋ฆฌ

์ด ๋ฌธ์ œ๋ฅผ ํ†ตํ•ด:

  • ๋ˆ„์ ํ•ฉ(Prefix Sum)
  • Hash Map์„ ์ด์šฉํ•œ ๊ตฌ๊ฐ„ํ•ฉ ์ตœ์ ํ™”

๊ฐœ๋…์„ ์—ฐ์Šตํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ์ด ๋ฌธ์ œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ,
Leetcode 2845. Count of Interesting Subarrays ๋ฌธ์ œ๋„ ์กฐ๊ธˆ ๋” ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์›Œ์งˆ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.


โœ… ํ•จ๊ป˜ ๋ณด๋ฉด ์ข‹์€ ๋ฌธ์ œ

  • Leetcode 523. Continuous Subarray Sum (์ด ๋ฌธ์ œ๋„ ๋ˆ„์ ํ•ฉ + ๋‚˜๋จธ์ง€ ํ™œ์šฉ)