알고리즘

알고리즘 특강 _ 2

zayn 2024. 10. 11. 21:10

[문제 1 _  없는 숫자 더하기]
문제 설명

0부터 9까지의 숫자 중 일부가 들어있는 정수 배열 numbers가 매개변수로 주어집니다. numbers에서 찾을 수 없는 0부터 9까지의 숫자를 모두 찾아 더한 수를 return 하도록 solution 함수를 완성해주세요.


제한사항
  • 1 ≤ numbers의 길이 ≤ 9
    • 0 ≤ numbers의 모든 원소 ≤ 9
    • numbers의 모든 원소는 서로 다릅니다.

 

입출력 예
numbers
result
[1,2,3,4,6,7,8,0] 14
[5,8,4,0,6,7,9] 6

 


 


입출력 예 설명

입출력 예 #1

  • 5, 9가 numbers에 없으므로, 5 + 9 = 14를 return 해야 합니다.

입출력 예 #2

  • 1, 2, 3이 numbers에 없으므로, 1 + 2 + 3 = 6을 return 해야 합니다.

[ 정답 ]

function solution(numbers) {
    // 0부터 9까지의 모든 숫자 합 계산
    const totalSum = 45; // 0 + 1 + 2 + ... + 9 = 45
    // numbers 배열의 요소 합 계산
    const numbersSum = numbers.reduce((acc, num) => acc + num, 0);
    // 찾지 못한 숫자들의 합은 전체 합에서 numbers의 합을 뺀 값
    return totalSum - numbersSum;
}


[설명]
1. totalSum: 0부터 9까지의 모든 숫자의 합은 45입니다.
2. numbersSum: 주어진 배열 `numbers`의 모든 요소를 합산합니다. `reduce` 메소드를 사용하여 배열의 모든 숫자를 더합니다.
3. 결과 반환: 전체 합 `totalSum`에서 `numbersSum`을 빼면 찾지 못한 숫자들의 합이 됩니다.


[문제 2 _ 핸드폰 번호 가리기]
 
문제 설명

프로그래머스 모바일은 개인정보 보호를 위해 고지서를 보낼 때 고객들의 전화번호의 일부를 가립니다.
전화번호가 문자열 phone_number로 주어졌을 때, 전화번호의 뒷 4자리를 제외한 나머지 숫자를 전부 *으로 가린 문자열을 리턴하는 함수, solution을 완성해주세요.

제한 조건
  • phone_number는 길이 4 이상, 20이하인 문자열입니다.

입출력 예

phone_number return
"01033334444" "*******4444"
"027778888" "*****8888"

[정답]
function solution(phone_number) {
    // 전화번호의 길이
    const length = phone_number.length;
    // 뒷 4자리를 제외한 나머지 부분을 *로 대체
    const maskedPart = '*'.repeat(length - 4);
    // 뒷 4자리와 합쳐서 결과 문자열을 생성
    const visiblePart = phone_number.slice(-4);
    return maskedPart + visiblePart;
}


[설명]
1. length: 전화번호의 전체 길이를 구합니다.
2. maskedPart: 전화번호의 뒷 4자리를 제외한 나머지 부분을 `*`로 대체합니다. `'*'.repeat(length - 4)`를 사용하여 전체 길이에서 4를 뺀 만큼 `*` 문자를 생성합니다.
3. visiblePart: 전화번호의 뒷 4자리를 `slice(-4)`를 사용해 잘라냅니다. `-4`는 문자열의 끝에서 4번째 자리부터 시작하여 잘라낸다는 의미입니다.
4. 결과 반환: `maskedPart`와 `visiblePart`를 합쳐서 최종 결과를 반환합니다.


[문제_3 나누어 떨어지는 숫자 배열]
문제 설명

array의 각 element 중 divisor로 나누어 떨어지는 값을 오름차순으로 정렬한 배열을 반환하는 함수, solution을 작성해주세요.
divisor로 나누어 떨어지는 element가 하나도 없다면 배열에 -1을 담아 반환하세요.

제한사항
  • arr은 자연수를 담은 배열입니다.
  • 정수 i, j에 대해 i ≠ j 이면 arr[i] ≠ arr[j] 입니다.
  • divisor는 자연수입니다.
  • array는 길이 1 이상인 배열입니다.
입출력 예
arr divisor return
[5, 9, 7, 10] 5 [5, 10]
[2, 36, 1, 3] 1 [1, 2, 3, 36]
[3,2,6] 10 [-1]

입출력 예 설명
 

입출력 예#1
arr의 원소 중 5로 나누어 떨어지는 원소는 5와 10입니다. 따라서 [5, 10]을 리턴합니다.
입출력 예#2
arr의 모든 원소는 1로 나누어 떨어집니다. 원소를 오름차순으로 정렬해 [1, 2, 3, 36]을 리턴합니다.
입출력 예#3
3, 2, 6은 10으로 나누어 떨어지지 않습니다. 나누어 떨어지는 원소가 없으므로 [-1]을 리턴합니다.


[ 정답 ]
function solution(arr, divisor) {
    // divisor로 나누어 떨어지는 요소 필터링
    const filtered = arr.filter(num => num % divisor === 0);
    
    // 필터링된 배열이 비어있으면 [-1] 반환
    if (filtered.length === 0) {
        return [-1];
    }
    
    // 필터링된 배열을 오름차순으로 정렬하여 반환
    return filtered.sort((a, b) => a - b);
}


[설명]
1. 필터링: `arr.filter(num => num % divisor === 0)`를 사용하여 배열 `arr`의 요소 중 `divisor`로 나누어 떨어지는 요소만 남기는 새로운 배열 `filtered`를 생성합니다.
2. 빈 배열 체크: `filtered.length`가 0이라면 나누어 떨어지는 요소가 없는 것이므로 `[-1]`을 반환합니다.
3. 정렬 및 반환: `filtered.sort((a, b) => a - b)`를 사용하여 남은 요소들을 오름차순으로 정렬한 후, 정렬된 배열을 반환합니다.


[문제 4_ 최소 직사각형]
문제 설명

명함 지갑을 만드는 회사에서 지갑의 크기를 정하려고 합니다. 다양한 모양과 크기의 명함들을 모두 수납할 수 있으면서, 작아서 들고 다니기 편한 지갑을 만들어야 합니다. 이러한 요건을 만족하는 지갑을 만들기 위해 디자인팀은 모든 명함의 가로 길이와 세로 길이를 조사했습니다.

아래 표는 4가지 명함의 가로 길이와 세로 길이를 나타냅니다.

명함 번호 가로 길이 세로 길이
1 60 50
2 30 70
3 60 30
4 80 40

가장 긴 가로길이와 세로 길이가 각각 80, 70이기 때문에 80(가로) x 70(세로) 크기의 지갑을 만들면 모든 명함들을 수납할 수 있습니다. 하지만 2번 명함을 가로로 눕혀 수납한다면 80(가로) x 50(세로) 크기의 지갑으로 모든 명함들을 수납할 수 있습니다. 이때의 지갑 크기는 4000(=80 x 50)입니다.
모든 명함의 가로길이와 세로 길이를 나타내는 2차원 배열 sizes가 매개변수로 주어집니다. 모든 명함을 수납할 수 있는 가장 작은 지갑을 만들 때, 지갑의 크기를 return 하도록 solution 함수를 완성해 주세요.


제한사항

  • sizes의 길이는 1 이상 10,000 이하입니다.
    • sizes의 원소는 [w, h] 형식입니다.
    • w는 명함의 가로 길이를 나타냅니다.
    • h는 명함의 세로 길이를 나타냅니다.
    • w와 h는 1 이상 1,000 이하인 자연수입니다.

입출력 예
 

sizesresult
[[60, 50], [30, 70], [60, 30], [80, 40]]4000
[[10, 7], [12, 3], [8, 15], [14, 7], [5, 15]]120
[[14, 4], [19, 6], [6, 16], [18, 7], [7, 11]]133

 


입출력 예 설명

입출력 예 #1
문제 예시와 같습니다.
입출력 예 #2
명함들을 적절히 회전시켜 겹쳤을 때, 3번째 명함(가로: 8, 세로: 15)이 다른 모든 명함보다 크기가 큽니다. 따라서 지갑의 크기는 3번째 명함의 크기와 같으며, 120(=8 x 15)을 return 합니다.
입출력 예 #3
명함들을 적절히 회전시켜 겹쳤을 때, 모든 명함을 포함하는 가장 작은 지갑의 크기는 133(=19 x 7)입니다.


[정답]
function solution(sizes) {
    let maxWidth = 0; // 최대 가로길이
    let maxHeight = 0; // 최대 세로 길이
    
    sizes.forEach(size => {
        const width = Math.max(size[0], size[1]); // 각 명함의 가로 세로 중 큰 값
        const height = Math.min(size[0], size[1]); // 각 명함의 가로 세로 중 작은 값
        
        maxWidth = Math.max(maxWidth, width); // 최대 가로길이 업데이트
        maxHeight = Math.max(maxHeight, height); // 최대 세로 길이 업데이트
    });
    
    return maxWidth * maxHeight; // 지갑의 크기 계산
}


[설명]
1. 변수 초기화: `maxWidth`와 `maxHeight`를 0으로 초기화합니다. 이 두 변수는 최종적으로 필요한 지갑의 크기를 결정하는 데 사용됩니다.
2. 명함 크기 확인: `sizes.forEach`를 사용하여 각 명함의 크기를 반복합니다.
   - `Math.max(size[0], size[1])`를 통해 가로와 세로 중 더 큰 값을 `width`에 저장합니다.
   - `Math.min(size[0], size[1])`를 통해 가로와 세로 중 더 작은 값을 `height`에 저장합니다.
3. 최대 크기 업데이트: `maxWidth`와 `maxHeight`를 업데이트하여 현재까지의 최대 가로 및 세로 길이를 유지합니다.
4. 지갑 크기 계산: 모든 명함을 수납할 수 있는 지갑의 크기는 `maxWidth * maxHeight`로 계산됩니다.
5. 결과 반환: 계산된 지갑의 크기를 반환합니다.
 
 
 
 
[ 느낀 점]
- 더 열심히 해야겠다..

'알고리즘' 카테고리의 다른 글

Q. 2016년  (0) 2024.10.28
알고리즘 특강_4  (1) 2024.10.15
알고리즘 특강_3  (0) 2024.10.15
알고리즘 특강_1  (1) 2024.10.10