rabbit97 님의 블로그
10일 일지 본문
주말동안 알고리즘 풀이에 한계가 와서 전에 풀었던 문제들을 다시 풀어보는 시간을 가졌다
확실히 처음 풀었을때 보다는 시야가 넓어진 것 같은 느낌이 들긴 하지만 이 문제들은 프로그래머스 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"))