πŸ“’ Algorithm/ν”„λ‘œκ·Έλž˜λ¨ΈμŠ€

[ν”„λ‘œκ·Έλž˜λ¨ΈμŠ€/LV.2] 두 큐 ν•© κ°™κ²Œ λ§Œλ“€κΈ°(JavaScript)

s2ylvia 2024. 11. 14. 19:02

https://school.programmers.co.kr/learn/courses/30/lessons/118667

 

문제 μ„€λͺ…

길이가 같은 두 개의 큐가 μ£Όμ–΄μ§‘λ‹ˆλ‹€. ν•˜λ‚˜μ˜ 큐λ₯Ό 골라 μ›μ†Œλ₯Ό μΆ”μΆœ(pop)ν•˜κ³ , μΆ”μΆœλœ μ›μ†Œλ₯Ό λ‹€λ₯Έ 큐에 μ§‘μ–΄λ„£λŠ”(insert) μž‘μ—…μ„ 톡해 각 큐의 μ›μ†Œ 합이 같도둝 λ§Œλ“€λ €κ³  ν•©λ‹ˆλ‹€. μ΄λ•Œ ν•„μš”ν•œ μž‘μ—…μ˜ μ΅œμ†Œ 횟수λ₯Ό κ΅¬ν•˜κ³ μž ν•©λ‹ˆλ‹€. ν•œ 번의 popκ³Ό ν•œ 번의 insertλ₯Ό ν•©μ³μ„œ μž‘μ—…μ„ 1회 μˆ˜ν–‰ν•œ κ²ƒμœΌλ‘œ κ°„μ£Όν•©λ‹ˆλ‹€.

νλŠ” λ¨Όμ € 집어넣은 μ›μ†Œκ°€ λ¨Όμ € λ‚˜μ˜€λŠ” κ΅¬μ‘°μž…λ‹ˆλ‹€. 이 λ¬Έμ œμ—μ„œλŠ” 큐λ₯Ό λ°°μ—΄λ‘œ ν‘œν˜„ν•˜λ©°, μ›μ†Œκ°€ λ°°μ—΄ μ•žμͺ½μ— μžˆμ„μˆ˜λ‘ λ¨Όμ € 집어넣은 μ›μ†Œμž„μ„ μ˜λ―Έν•©λ‹ˆλ‹€. 즉, pop을 ν•˜λ©΄ λ°°μ—΄μ˜ 첫 번째 μ›μ†Œκ°€ μΆ”μΆœλ˜λ©°, insertλ₯Ό ν•˜λ©΄ λ°°μ—΄μ˜ 끝에 μ›μ†Œκ°€ μΆ”κ°€λ©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ 큐 [1, 2, 3, 4]κ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, pop을 ν•˜λ©΄ 맨 μ•žμ— μžˆλŠ” μ›μ†Œ 1이 μΆ”μΆœλ˜μ–΄ [2, 3, 4]κ°€ 되며, μ΄μ–΄μ„œ 5λ₯Ό insertν•˜λ©΄ [2, 3, 4, 5]κ°€ λ©λ‹ˆλ‹€.

λ‹€μŒμ€ 두 큐λ₯Ό λ‚˜νƒ€λ‚΄λŠ” μ˜ˆμ‹œμž…λ‹ˆλ‹€.
queue1 = [3, 2, 7, 2]
queue2 = [4, 6, 5, 1]​


두 큐에 λ‹΄κΈ΄ λͺ¨λ“  μ›μ†Œμ˜ 합은 30μž…λ‹ˆλ‹€. λ”°λΌμ„œ, 각 큐의 합을 15둜 λ§Œλ“€μ–΄μ•Ό ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, λ‹€μŒκ³Ό 같이 2κ°€μ§€ 방법이 μžˆμŠ΅λ‹ˆλ‹€.

1. queue2의 4, 6, 5λ₯Ό μˆœμ„œλŒ€λ‘œ μΆ”μΆœν•˜μ—¬ queue1에 μΆ”κ°€ν•œ λ’€, queue1의 3, 2, 7, 2λ₯Ό μˆœμ„œλŒ€λ‘œ μΆ”μΆœν•˜μ—¬ queue2에 μΆ”κ°€ν•©λ‹ˆλ‹€. κ·Έ κ²°κ³Ό queue1은 [4, 6, 5], queue2λŠ” [1, 3, 2, 7, 2]κ°€ 되며, 각 큐의 μ›μ†Œ 합은 15둜 κ°™μŠ΅λ‹ˆλ‹€. 이 방법은 μž‘μ—…μ„ 7번 μˆ˜ν–‰ν•©λ‹ˆλ‹€.
2. queue1μ—μ„œ 3을 μΆ”μΆœν•˜μ—¬ queue2에 μΆ”κ°€ν•©λ‹ˆλ‹€. 그리고 queue2μ—μ„œ 4λ₯Ό μΆ”μΆœν•˜μ—¬ queue1에 μΆ”κ°€ν•©λ‹ˆλ‹€. κ·Έ κ²°κ³Ό queue1은 [2, 7, 2, 4], queue2λŠ” [6, 5, 1, 3]κ°€ 되며, 각 큐의 μ›μ†Œ 합은 15둜 κ°™μŠ΅λ‹ˆλ‹€. 이 방법은 μž‘μ—…μ„ 2번만 μˆ˜ν–‰ν•˜λ©°, 이보닀 적은 횟수둜 λͺ©ν‘œλ₯Ό 달성할 수 μ—†μŠ΅λ‹ˆλ‹€.

λ”°λΌμ„œ 각 큐의 μ›μ†Œ 합을 κ°™κ²Œ λ§Œλ“€κΈ° μœ„ν•΄ ν•„μš”ν•œ μž‘μ—…μ˜ μ΅œμ†Œ νšŸμˆ˜λŠ” 2μž…λ‹ˆλ‹€.

길이가 같은 두 개의 큐λ₯Ό λ‚˜νƒ€λ‚΄λŠ” μ •μˆ˜ λ°°μ—΄ queue1, queue2κ°€ λ§€κ°œλ³€μˆ˜λ‘œ μ£Όμ–΄μ§‘λ‹ˆλ‹€. 각 큐의 μ›μ†Œ 합을 κ°™κ²Œ λ§Œλ“€κΈ° μœ„ν•΄ ν•„μš”ν•œ μž‘μ—…μ˜ μ΅œμ†Œ 횟수λ₯Ό return ν•˜λ„λ‘ solution ν•¨μˆ˜λ₯Ό μ™„μ„±ν•΄μ£Όμ„Έμš”. 단, μ–΄λ–€ λ°©λ²•μœΌλ‘œλ„ 각 큐의 μ›μ†Œ 합을 κ°™κ²Œ λ§Œλ“€ 수 μ—†λŠ” 경우, -1을 return ν•΄μ£Όμ„Έμš”.

 

 

μ œν•œ 사항

  • 1 ≤ queue1의 길이 = queue2의 길이 ≤ 300,000
  • 1 ≤ queue1의 μ›μ†Œ, queue2의 μ›μ†Œ ≤ 109
  • 주의: 언어에 따라 ν•© 계산 κ³Όμ • 쀑 μ‚°μˆ  μ˜€λ²„ν”Œλ‘œμš° λ°œμƒ κ°€λŠ₯성이 μžˆμœΌλ―€λ‘œ long type κ³ λ €κ°€ ν•„μš”ν•©λ‹ˆλ‹€.

 

μž…μΆœλ ₯ 예

queue1 queue2 result
[3, 2, 7, 2] [4, 6, 5, 1] 2
[1, 2, 1, 2] [1, 10, 1, 2] 7
[1, 1] [1, 5] -1

 

 

μž…μΆœλ ₯ 예 μ„€λͺ…

 

μž…μΆœλ ₯ 예 #1

문제 μ˜ˆμ‹œμ™€ κ°™μŠ΅λ‹ˆλ‹€.

 

μž…μΆœλ ₯ 예 #2

두 큐에 λ‹΄κΈ΄ λͺ¨λ“  μ›μ†Œμ˜ 합은 20μž…λ‹ˆλ‹€. λ”°λΌμ„œ, 각 큐의 합을 10으둜 λ§Œλ“€μ–΄μ•Ό ν•©λ‹ˆλ‹€. queue2μ—μ„œ 1, 10을 μˆœμ„œλŒ€λ‘œ μΆ”μΆœν•˜μ—¬ queue1에 μΆ”κ°€ν•˜κ³ , queue1μ—μ„œ 1, 2, 1, 2와 1(queue2μœΌλ‘œλΆ€ν„° 받은 μ›μ†Œ)을 μˆœμ„œλŒ€λ‘œ μΆ”μΆœν•˜μ—¬ queue2에 μΆ”κ°€ν•©λ‹ˆλ‹€. κ·Έ κ²°κ³Ό queue1은 [10], queue2λŠ” [1, 2, 1, 2, 1, 2, 1]κ°€ 되며, 각 큐의 μ›μ†Œ 합은 10으둜 κ°™μŠ΅λ‹ˆλ‹€. μ΄λ•Œ μž‘μ—… νšŸμˆ˜λŠ” 7회이며, 이보닀 적은 횟수둜 λͺ©ν‘œλ₯Ό λ‹¬μ„±ν•˜λŠ” 방법은 μ—†μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ 7λ₯Ό return ν•©λ‹ˆλ‹€.

 

μž…μΆœλ ₯ 예 #3

μ–΄λ–€ 방법을 쓰더라도 각 큐의 μ›μ†Œ 합을 κ°™κ²Œ λ§Œλ“€ 수 μ—†μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ -1을 return ν•©λ‹ˆλ‹€.

 


 

μ •λ‹΅ μ½”λ“œ

function solution(queue1, queue2) {
    //이 λΉΌκ³  λ„£κ³ μ˜ 기쀀을 μ–΄λ–»κ²Œ μ„ΈμšΈκΉŒ?
    //막 적닀가 λΉΌμ•Όλ˜λŠ” 즉, 합이 더 큰 νμ—μ„œ popλ₯Ό ν•˜λ©΄ λ˜κ² λ‹€λŠ” 생각을 ν–ˆλ‹€!
    //그리고 queue의 길이가 μ΅œλŒ€ μ‚Όμ‹­λ§Œμ΄κΈ° λ•Œλ¬Έμ— μ‹œκ°„μ΄ˆκ³Όκ°€ 무쑰건 λ‚  것 κ°™λ‹€!
    //κ·Έλž˜μ„œ shift()λ₯Ό 쓰지말고 인덱슀λ₯Ό μ‚¬μš©ν•΄μ•Όν–ˆλ‹€.
    
    let count = 0; //μž‘μ—… 횟수
    const totalLength = queue1.length + queue2.length; //μ’…λ£Œμ‘°κ±΄μ„ μœ„ν•΄ μ΅œμ’… 길이λ₯Ό ꡬ해쀀닀.
    let queue1Idx = 0; //맨 μ•žμ—μ„œλΆ€ν„° λΉΌμ•Όν•˜λ‹ˆκΉ
    let queue2Idx = 0;
    
    let queue1Sum = queue1.reduce((a,b) => a+b,0);
    let queue2Sum = queue2.reduce((a,b) => a+b,0);
    
    while(queue1Sum !== queue2Sum){
        //같을 λ•ŒκΉŒμ§€ λŒλ €μ•Όν•œλ‹€.
        if(queue1Sum > queue2Sum){
            //1큐가 더 크면 1νμ—μ„œ λΉΌμ„œ 2큐둜
            queue1Sum -= queue1[queue1Idx];
            queue2.push(queue1[queue1Idx]);
            queue2Sum += queue1[queue1Idx]; //pushλœλ‹€κ³  μžλ™μœΌλ‘œ λ‹€μ‹œ sum을 κ΅¬ν•˜λŠ”κ²Œ μ•„λ‹ˆκΈ°λ•Œλ¬Έμ— 직접 더해쀀닀.
            queue1Idx++; //그리고 인덱슀 증가
        }else if(queue1Sum < queue2Sum){
            //2큐가 더 크면 2νμ—μ„œ λΉΌμ„œ 1큐둜
            queue2Sum -= queue2[queue2Idx];
            queue1.push(queue2[queue2Idx]);
            queue1Sum += queue2[queue2Idx];
            queue2Idx++;
        }
        
        count++; //카운트 μ˜¬λ €μ£ΌλŠ”κ±΄ κ³΅ν†΅μ΄λ‹ˆκΉ λ°–μœΌλ‘œ
        
        if(queue1Idx > totalLength || queue2Idx > totalLength){
            //μΈλ±μŠ€κ°€ ν† νƒˆλ³΄λ‹€ 크면 큐λ₯Ό λ‹€ 돈거겠죠?
            return -1;
        }
    }
    
    return count;
}