Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

rabbit97 님의 블로그

10일 일지 본문

개발 일지

10일 일지

rabbit97 2024. 11. 10. 19:30

주말동안 알고리즘 풀이에 한계가 와서 전에 풀었던 문제들을 다시 풀어보는 시간을 가졌다

 

확실히 처음 풀었을때 보다는 시야가 넓어진 것 같은 느낌이 들긴 하지만 이 문제들은 프로그래머스 0~1레벨 문제이다

 

3레벨이 목표인데 갈 길이 멀구나

 

개인적으로 풀이가 많이 달라졌거나 어려웠던 부분을 기록할까 하는데

 

지금 생각해보면 스타일이 많이 달라졌다

 

솔루션 함수에 모든 로직을 넣었었는데 기능별로 나누는 연습이 선호하는 스타일을 만들어 낸 것 같다

 

 

 

 

 

33번 문제 약수의 갯수와 덧셈

// 문제 설명
// 두 정수 left와 right가 매개변수로 주어집니다. left부터 right까지의 모든 수들 중에서, 약수의 개수가 짝수인 수는 더하고,
// 약수의 개수가 홀수인 수는 뺀 수를 return 하도록 solution 함수를 완성해주세요.
//
//     제한사항
// 1 ≤ left ≤ right ≤ 1,000
// 입출력 예
// left right  result
// 13   17 43
// 24   27 52
// 입출력 예 설명
// 입출력 예 #1
//
// 다음 표는 13부터 17까지의 수들의 약수를 모두 나타낸 것입니다.
//     수    약수 약수의 개수
// 13   1, 13  2
// 14   1, 2, 7, 14    4
// 15   1, 3, 5, 15    4
// 16   1, 2, 4, 8, 16 5
// 17   1, 17  2
// 따라서, 13 + 14 + 15 - 16 + 17 = 43을 return 해야 합니다.
//     입출력 예 #2
//
// 다음 표는 24부터 27까지의 수들의 약수를 모두 나타낸 것입니다.
//     수    약수 약수의 개수
// 24   1, 2, 3, 4, 6, 8, 12, 24   8
// 25   1, 5, 25   3
// 26   1, 2, 13, 26   4
// 27   1, 3, 9, 27    4
// 따라서, 24 - 25 + 26 + 27 = 52를 return 해야 합니다.
function solution(left, right) {
    // 두 숫자 왼쪽과 오른쪽 사이의 모든 값들의 약수를 구해야함
    // 반복을 돌기 전 각 수의 약수의 갯수를 먼저 구하고 마지막에 더할지 뺄지 정하기
    let answer = 0;
    let arr = []

    // 만약 왼쪽 숫자가 더 크다면?? - 일단 조건문으로 거르기
    if (left < right) {
        for (let i = left; i <= right; i++) {
            // 배열에 각 숫자들을 먼저 넣기
            arr.push(i)
        }
        console.log(arr)
        // 배열에 들어간 값들 각각 약수의 갯수 구하기
        // (어떻게?) - 약수는 나눈 값의 나머지가 0이 되는 수
        // 1. 제곱근(예시: Math.sqrt(n))을 이용한다면?
        // 2. *약수의 갯수를 계산하는 함수 하나를 더 추가하고 매개변수로는 반복을 돌고있는
        // 배열의 n을 준 다음 카운트를 계산한다면?* (채택)
        for (let i = 0; i < arr.length; i++) {
            const n = arr[i]

            const divisor = divisorCount(n)

            if (divisor % 2 === 0) {
                answer += n;
            } else {
                answer -= n;
            }
        }
    }

    // 테스트가 통과했음은 왼쪽이 더 큰 경우가 없었기에 로직 구현 x
    if (left > right) {
        console.error("왼쪽이 더 크다!!!! 뭔가 잘못됐다!!! 다시 로직 개선하자!!!!!!!")
    }

    return answer;
}

// 약수의 갯수를 구하는 함수
function divisorCount(n) {
    let count = 0;
    for (let i = 1; i <= n; i++) {
        if (n % i === 0) {
            count++;
        }
    }
    return count;
}

console.log(solution(13, 17))
console.log(solution(24, 27))
console.log(solution(1, 1000))
console.log(solution(1000, 1))

 

 

 

 

 

39번 문제 최대공약수와 최소공배수

// 문제 설명
// 두 수를 입력받아 두 수의 최대공약수와 최소공배수를 반환하는 함수, solution을 완성해 보세요.
// 배열의 맨 앞에 최대공약수, 그다음 최소공배수를 넣어 반환하면 됩니다. 예를 들어 두 수 3, 12의 최대공약수는 3,
// 최소공배수는 12이므로 solution(3, 12)는 [3, 12]를 반환해야 합니다.
//
//     제한 사항
// 두 수는 1이상 1000000이하의 자연수입니다.
//     입출력 예
// n    m  return
// 3    12 [3, 12]
// 2    5  [1, 10]
// 입출력 예 설명
// 입출력 예 #1
// 위의 설명과 같습니다.
//
//     입출력 예 #2
// 자연수 2와 5의 최대공약수는 1, 최소공배수는 10이므로 [1, 10]을 리턴해야 합니다.

function solution(n, m) {
    // 두 수의 최대공약수를 첫번째 최소공배수는 두번째 위치에 배열에 넣어야함
    // 최대공약수(GCD) - 두 수의 공통된 약수중 가장 큰 수
    // 최소공배수(LCM) - 두 수의 공통된 배수중 가장 작은 수
    // 최대 공약수를 구하는 함수 하나 최소 공배수를 구하는 함수 하나를 선언하고 solution 함수에서 반환값만 정해주기

    const gcdValue = GCD(n, m);
    const lcmValue = LCM(n, m);
    return [gcdValue, lcmValue];
}


// n과 m의 약수 구하기
function getDivisors(num) {
    const divisors = [];
    for (let i = 1; i <= num; i++) {
        if (num % i === 0) {
            divisors.push(i);
        }
    }
    return divisors;
}

console.log(getDivisors(3))
console.log(getDivisors(12))

// 두 수의 최대공약수를 구하는 함수
function GCD(n, m) {
    const nFromGcd = getDivisors(n);
    const mFromGcd = getDivisors(m);

    // 두 수의 공통된 약수 구하기
    const commonDivisors = nFromGcd.filter(value => mFromGcd.includes(value));

    // 공통 약수 중 가장 큰 값 반환
    return Math.max(...commonDivisors);
}

console.log(GCD(3, 12))

// 두 수의 최소공배수를 구하는 함수
function LCM(n, m) {
    return (n * m) / GCD(n, m);
}

console.log(LCM(3, 12))


console.log(solution(3, 12));
console.log(solution(2, 5));




 

43번 문제 크기가 작은 부분

 

// 문제 설명
// 숫자로 이루어진 문자열 t와 p가 주어질 때, t에서 p와 길이가 같은 부분문자열 중에서,
// 이 부분문자열이 나타내는 수가 p가 나타내는 수보다 작거나 같은 것이 나오는 횟수를 return하는 함수 solution을 완성하세요.
//
//     예를 들어, t="3141592"이고 p="271" 인 경우, t의 길이가 3인 부분 문자열은 314, 141, 415, 159, 592입니다.
//     이 문자열이 나타내는 수 중 271보다 작거나 같은 수는 141, 159 2개 입니다.
//
//     제한사항
// 1 ≤ p의 길이 ≤ 18
// p의 길이 ≤ t의 길이 ≤ 10,000
// t와 p는 숫자로만 이루어진 문자열이며, 0으로 시작하지 않습니다.
//     입출력 예
// t    p  result
// "3141592"    "271"  2
// "500220839878"   "7"    8
// "10203"  "15"   3
// 입출력 예 설명
// 입출력 예 #1
// 본문과 같습니다.
//
//     입출력 예 #2
// p의 길이가 1이므로 t의 부분문자열은 "5", "0", 0", "2", "2", "0", "8", "3", "9", "8", "7", "8"이며
// 이중 7보다 작거나 같은 숫자는 "5", "0", "0", "2", "2", "0", "3", "7" 이렇게 8개가 있습니다.
//
// 입출력 예 #3
// p의 길이가 2이므로 t의 부분문자열은 "10", "02", "20", "03"이며, 이중 15보다 작거나 같은 숫자는 "10", "02", "03" 이렇게 3개입니다.
// "02"와 "03"은 각각 2, 3에 해당한다는 점에 주의하세요

function solution(t, p) {
    // t는 p의 길이 만큼만 봐야하며 그 중 p보다 낮은 수를 count
    // t의 길이는 무조건 p보다 길이가 같거나 크기때문에 예외처리 x
    // t를 반복문을 먼저 돌고 조건으로는 t의 길이 식으로는 p의 길이만큼 자르고 배열에 넣기
    // 반복은 함수 하나를 더 만들어서 진행하고 솔루션 함수에서는 count만 계산
    const pLength = p.length;
    const tArr = TFromPLengthArr(t, pLength);
    return countLessOrEqual(tArr, p);
}

// t를 p의 길이 만큼 나눈 숫자들을 배열에 넣는 함수
function TFromPLengthArr(t, pLength) {
    let tArr = [];
    for (let i = 0; i <= t.length - pLength; i++) {
        tArr.push(t.slice(i, i + pLength));
    }
    return tArr;
}

// 조건을 만족하는 부분문자열의 개수를 세는 함수를 추가
function countLessOrEqual(tArr, p) {
    const pNumber = Number(p);
    let count = 0;

    tArr.forEach(subString => {
        if (Number(subString) <= pNumber) {
            count++;
        }
    });

    return count;
}

console.log(solution("3141592", "271"))

 

'개발 일지' 카테고리의 다른 글

8일 일지  (0) 2024.11.08
6일 일지  (2) 2024.11.06
5일 일지  (4) 2024.11.05
1일 일지  (0) 2024.11.01
31일 일지  (0) 2024.10.31