๋ฐ˜์‘ํ˜•

์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ฐœ๋…


์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜(Sliding Window Algorithm)์€ ๋ฐฐ์—ด๊ณผ ๊ฐ™์€ ์„ ํ˜• ์ž๋ฃŒ๊ตฌ์กฐ์—์„œ ์—ฐ์†๋œ ๊ตฌ๊ฐ„ ๋‚ด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ฒ•์ด๋‹ค. ํŠนํžˆ ๋ฐฐ์—ด ๋‚ด ์—ฐ์†๋œ ์š”์†Œ์˜ ํ•ฉ, ์ตœ๋Œ“๊ฐ’, ์ตœ์†Ÿ๊ฐ’ ๋“ฑ์„ ๊ณ„์‚ฐํ•  ๋•Œ ์œ ์šฉํ•˜๋‹ค.

 

์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ๋Š” ์ด๋ฆ„ ๊ทธ๋Œ€๋กœ ๊ณ ์ •/๊ฐ€๋ณ€ ํฌ๊ธฐ์˜ ๋ฒ”์œ„(์œˆ๋„์šฐ)๋ฅผ ์ด๋™(์Šฌ๋ผ์ด๋“œ) ์‹œํ‚ค๋ฉด์„œ ํ•„์š”ํ•œ ๊ณ„์‚ฐ์„ ๋ฐ˜๋ณตํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. ์ด๋•Œ ์ „์ฒด ๋ฐฐ์—ด์„ ํ•œ ๋ฒˆ๋งŒ ์ˆœํšŒํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ค‘๋ณต ์—ฐ์‚ฐ์„ ํ”ผํ•˜๊ณ  ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด O(n)์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

// ์ฃผ์–ด์ง„ ๋ฐฐ์—ด์—์„œ ์—ฐ์†๋œ k๊ฐœ ์š”์†Œ์˜ ์ตœ๋Œ€ ํ•ฉ์„ ์ฐพ๋Š” ํ•จ์ˆ˜
function maxSumSubarray(arr, k) {
  let maxSum = 0;
  let windowSum = 0;

  // ์ดˆ๊ธฐ ์œˆ๋„์šฐ(k๊ฐœ์˜ ์š”์†Œ) ํ•ฉ ๊ณ„์‚ฐ
  for (let i = 0; i < k; i++) {
    windowSum += arr[i];
  }
  maxSum = windowSum;

  // ์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ ์ด๋™
  for (let end = k; end < arr.length; end++) {
    const start = end - k;
    // arr[end]๊ฐ€ ์ƒˆ๋กœ ์ถ”๊ฐ€๋˜๋Š” ์š”์†Œ ์ด๋ฏ€๋กœ arr[end] - arr[start] ์ˆœ์„œ๋กœ ๊ณ„์‚ฐ
    windowSum += arr[end] - arr[start];
    maxSum = Math.max(maxSum, windowSum);
  }

  return maxSum;
}

const result = maxSumSubarray([2, 1, 5, 1, 3, 2], 3);
console.log(result); // 9

 

์œ„ ์˜ˆ์‹œ๋Š” ์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐฐ์—ด ๋‚ด ์—ฐ์†๋œ k๊ฐœ ์š”์†Œ์˜ ์ตœ๋Œ€ ํ•ฉ์„ ์ฐพ๋Š” ํ•จ์ˆ˜๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ดˆ๊ธฐ ๋ฐฐ์—ด [2, 1, 5, 1, 3, 2] ์—์„œ ์ฒ˜์Œ 3๊ฐœ ์š”์†Œ์˜ ํ•ฉ์€ 2 + 1 + 5 = 8 ์ด๋‹ค. ์ดํ›„ ์œˆ๋„์šฐ๋ฅผ ํ•œ ์นธ์”ฉ ์ด๋™ํ•˜๋ฉด์„œ k๊ฐœ์˜ ์š”์†Œ๋ฅผ ๋”ํ•ด ๋‚˜๊ฐ„๋‹ค.

 

  • (215)132 → 2 + 1 + 5 = 8
  • 2(151)32 → 1 + 5 + 1 = 7
  • 21(513)2 → 5 + 1 + 3 = 9 (์ตœ๋Œ“๊ฐ’)
  • 215(132) → 1 + 3 + 2 = 6

 

ํ•œํŽธ ๋งค๋ฒˆ ์œˆ๋„์šฐ์— ์žˆ๋Š” ๋ชจ๋“  k๊ฐœ ์š”์†Œ๋ฅผ ๋ฐ˜๋ณตํ•ด์„œ ๋”ํ•  ํ•„์š” ์—†์ด, ์ด์ „ ์œˆ๋„์šฐ์—์„œ ๊ณ„์‚ฐํ•œ ๊ฐ’์—, ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•  ์š”์†Œ์™€ ์ œ๊ฑฐํ•  ์š”์†Œ๋ฅผ ๋ฐ˜์˜ํ•˜๋ฉด ํ•ฉ๊ณ„๋ฅผ ๋” ํšจ์œจ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด์ „ ์œˆ๋„์šฐ ๊ณ„์‚ฐ๊ฐ’ + (์ถ”๊ฐ€ํ•˜๋Š” ์š”์†Œ - ๋น ์ง€๋Š” ์š”์†Œ)

 

์‹œ๊ฐ์ ์œผ๋กœ ํ‘œํ˜„ํ•ด ๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ ๊ธฐ๋ฒ•์œผ๋กœ ๋ฐฐ์—ด๋‚ด ์—ฐ์†๋œ k๊ฐœ ์š”์†Œ์˜ ์ตœ๋Œ€ ํ•ฉ์„ ์ฐพ๋Š” ๊ณผ์ •

 

์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํ™œ์šฉ


ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ ˆ๋ฒจ 2 - ํ• ์ธํ–‰์‚ฌ ๋ฌธ์ œ(131127)๋„ ์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ ๊ธฐ๋ฒ•์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฃผ์–ด์ง„ ํ• ์ธ ๋ชฉ๋ก(discount)์—์„œ 10์ผ ์—ฐ์† ๊ตฌ๊ฐ„์— ํฌํ•จ๋˜์–ด ์žˆ๋Š” ์ œํ’ˆ/์ˆ˜๋Ÿ‰๊ณผ, ๊ตฌ๋งคํ•˜๊ณ  ์‹ถ์€ ์ œํ’ˆ/์ˆ˜๋Ÿ‰์ด ์ •ํ™•ํžˆ ์ผ์น˜ํ•˜๋Š” ๊ฒฝ์šฐ์˜ ์ด๊ฐœ์ˆ˜๋ฅผ ๊ตฌํ•˜๋Š” ๋ฌธ์ œ๋‹ค.

 

  • want: ๊ตฌ๋งค ์ œํ’ˆ ๋ชฉ๋ก (๋ฐฐ์—ด)
  • number: ๊ตฌ๋งค ์ œํ’ˆ ์ˆ˜๋Ÿ‰ (๋ฐฐ์—ด, want ๋ฐฐ์—ด ์ธ๋ฑ์Šค์™€ ๋งคํ•‘)
  • discount : ํ• ์ธ ์ œํ’ˆ ๋ชฉ๋ก (๋ฐฐ์—ด, ๊ฐ ์ธ๋ฑ์Šค๋Š” ๋‚ ์งœ๋ฅผ ๊ฐ€๋ฆฌํ‚ด)

 

๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด discount ๋ฐฐ์—ด์„ 0๋ฒˆ ์ธ๋ฑ์Šค๋ถ€ํ„ฐ ์ˆœํšŒํ•˜๋ฉด์„œ, ํ•ด๋‹น ์œ„์น˜์—์„œ ์‹œ์ž‘ํ•˜๋Š” 10์ผ ๊ตฌ๊ฐ„์˜ ํ• ์ธ ์ œํ’ˆ/์ˆ˜๋Ÿ‰์ด, ๊ตฌ๋งค ์ œํ’ˆ/์ˆ˜๋Ÿ‰๊ณผ ์ผ์น˜ํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๋ฉด ๋œ๋‹ค.

 

์ด๋•Œ 10์ผ ๊ตฌ๊ฐ„์˜ ๋ชจ๋“  ์ œํ’ˆ ์ˆ˜๋Ÿ‰์„ ๋งค๋ฒˆ ๊ณ„์‚ฐํ•  ํ•„์š” ์—†์ด, ์ด์ „ ๊ตฌ๊ฐ„์—์„œ ๊ณ„์‚ฐํ•œ ์œˆ๋„์šฐ ์ •๋ณด์— ์ถ”๊ฐ€/์ œ๊ฑฐ๋˜๋Š” ์ œํ’ˆ์˜ ์ˆ˜๋Ÿ‰๋งŒ ์กฐ์ ˆํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

const WINDOW_SIZE = 10;

function solution(want, number, discount) {
  const wantMap = want.reduce((map, item, i) => map.set(item, number[i]), new Map());
  const windowMap = new Map();
  let count = 0;

  // ์ดˆ๊ธฐ ์œˆ๋„์šฐ ์„ค์ • (์ฒซ 10์ผ)
  // chicken => 1, apple => 3, banana => 2, rice => 2, pork => 2
  for (let i = 0; i < WINDOW_SIZE; i++) {
    windowMap.set(discount[i], (windowMap.get(discount[i]) ?? 0) + 1);
  }

  // ํ˜„์žฌ ์œˆ๋„์šฐ๊ฐ€ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š”์ง€ ํ™•์ธ
  const checkIfValid = () => {
    for (const [item, qty] of wantMap.entries()) {
      if ((windowMap.get(item) ?? 0) < qty) return false;
    }
    return true;
  };

  // ์ฒซ 10์ผ ์ฒดํฌ
  if (checkIfValid()) count++;

  // ์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ๋กœ ํƒ์ƒ‰
  for (let i = WINDOW_SIZE; i < discount.length; i++) {
    const oldItem = discount[i - WINDOW_SIZE]; // ์ด์ „ ํ•ญ๋ชฉ ์ œ๊ฑฐ
    const newItem = discount[i]; // ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ํ•ญ๋ชฉ ์ถ”๊ฐ€

    // ์œˆ๋„์šฐ ์—…๋ฐ์ดํŠธ
    // i10 = chicken => 1, apple => 3, banana => 2, rice => 2, pork => 2
    // i11 = chicken => 0, apple => 3, banana => 2, rice => 2, pork => 2, pot => 1
    // i12 = chicken => 0, apple => 2, banana => 3, rice => 2, pork => 2, pot => 1
    // ...
    windowMap.set(oldItem, windowMap.get(oldItem) - 1);
    windowMap.set(newItem, (windowMap.get(newItem) ?? 0) + 1);

    // ์กฐ๊ฑด ๋งŒ์กฑ ์—ฌ๋ถ€ ์ฒดํฌ
    if (checkIfValid()) count++;
  }

  return count;
}
๋”๋ณด๊ธฐ
const want = ["banana", "apple", "rice", "pork", "pot"];
const number = [3, 2, 2, 2, 1];
const discount = [
  "chicken",
  "apple",
  "apple",
  "banana",
  "rice",
  "apple",
  "pork",
  "banana",
  "pork",
  "rice",
  "pot",
  "banana",
  "apple",
  "banana",
];

const result = solution(want, number, discount);
console.log(result); // 3

 

  1. ๊ตฌ๋งคํ•ด์•ผ ํ•˜๋Š” ์ œํ’ˆ ๋ชฉ๋ก/์ˆ˜๋Ÿ‰์„ ๋งคํ•‘ํ•œ Map ์ƒ์„ฑ (wantMap)
  2. ์ดˆ๊ธฐ ์œˆ๋„์šฐ Map ์ƒ์„ฑ (windowMap)
  3. ์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ๋กœ discount ๋ฐฐ์—ด ํƒ์ƒ‰ ๋ฐ windowMap ์—…๋ฐ์ดํŠธ
  4. ์—…๋ฐ์ดํŠธํ•œ windowMap๊ณผ wantMap ๋น„๊ต

 

์œ„ ๊ณผ์ •์„ ์‹œ๊ฐ์ ์œผ๋กœ ํ‘œํ˜„ํ•ด ๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ ๊ธฐ๋ฒ•์œผ๋กœ discount ๋ฐฐ์—ด์„ ํƒ์ƒ‰ํ•˜๋ฉด์„œ ์œˆ๋„์šฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ณผ์ •

 


๊ธ€ ์ˆ˜์ •์‚ฌํ•ญ์€ ๋…ธ์…˜ ํŽ˜์ด์ง€์— ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”

 

 
๋ฐ˜์‘ํ˜•