Algorithm - Day 1

Algorithm-Test

목록 보기
1/17
post-thumbnail

매일 알고리즘 3문제씩 풀기 챌린지 1일차 👊🏻

Q1. 피자 나눠먹기

https://school.programmers.co.kr/learn/courses/30/lessons/120814
머쓱이네 피자가게는 피자를 일곱 조각으로 잘라 줍니다. 피자를 나눠먹을 사람의 수 n이 주어질 때, 모든 사람이 피자를 한 조각 이상 먹기 위해 필요한 피자의 수를 return 하는 solution 함수를 완성해보세요.

내 풀이

function solution(n) {
    var answer = 0;

    if(n % 7 === 0) answer = parseInt(n / 7);
    else answer = parseInt(n / 7) + 1;

    return answer;
}

오답노트

  • if ... else 문을 썼는데, 그냥 간단히 ? 연산자를 썼어도 됐을 듯
  • 어차피 n % 7 === 0 이면 n / 7 도 정수라 굳이 parseInt를 쓸 필요가 없음
function solution(n) {
    var answer = 0;

    return (n % 7 === 0) ? n / 7 : parseInt(n / 7) + 1;
}

다른 접근 방식

  • Math 함수를 사용하면 조건 분기 없이 깔끔!
function solution(n) {
    return Math.ceil(n / 7)
}

✏️ 주요 개념 공부

  • Math.ceil() 정적 메서드는 언제나 올림하여 주어진 숫자보다 크거나 같은 가장 작은 정수를 반환
  • cf) Math.floor() 정적 메서드는 언제나 버림 처리하고 주어진 숫자와 같거나 작은 정수 중에서 가장 큰 정수를 반환
  • Math.round() 는 입력값을 반올림한 수와 가장 가까운 정수 값을 반환
  • Math.trunc() 는 숫자의 소수 부분을 제거한 숫자의 정수 부분을 반환
입력값Math.ceil()Math.floor()Math.trunc()Math.round()
-Infinity-Infinity-Infinity-Infinity-Infinity
-7.004-7-8-7-7
-4-4-4-4-4
-0.95-0-1-0-1
-0-0-0-0-0
00000
0.951001
44444
7.0048777
InfinityInfinityInfinityInfinityInfinity

Q2. 특정 문자 제거하기

https://school.programmers.co.kr/learn/courses/30/lessons/120826
문자열 my_string과 문자 letter이 매개변수로 주어집니다. my_string에서 letter를 제거한 문자열을 return하도록 solution 함수를 완성해주세요.

  • 1 ≤ my_string의 길이 ≤ 100
  • letter은 길이가 1인 영문자입니다.
  • my_string과 letter은 알파벳 대소문자로 이루어져 있습니다.
  • 대문자와 소문자를 구분합니다.

내 풀이

  • 처음에 복잡하게 생각했었는데 string prototype 찍고 보다보니까 replaceAll()이 있어서 사용함..
function solution(my_string, letter) {
    return my_string.replaceAll(letter,'')
}

다른 접근 방식

  • string의 다른 메서드인 split() 을 사용한 방식이 꽤나 신박
  • target letter를 기준으로 나눠버리면 해당 문자가 없어지니까, 그리고나서 나온 array를 join 해버리기
function solution(my_string, letter) {
    const answer = my_string.split(letter).join('')
    return answer;
}

✏️ 주요 개념 공부

[ String 메서드 / 유틸 함수 ]

함수명역할예시
charAt()특정 위치의 문자 반환'hello'.charAt(1)'e'
concat()문자열을 결합'Hello'.concat(' ', 'World')'Hello World'
includes()문자열 포함 여부 확인'JavaScript'.includes('Script')true
indexOf()특정 문자열의 첫 위치 반환'banana'.indexOf('a')1
lastIndexOf()특정 문자열의 마지막 위치 반환'banana'.lastIndexOf('a')5
slice()문자열 일부 (beginIndex ~ endIndex) 추출'hello'.slice(1, 3)'el'(1 ~ 3번째 직전)
'banana'.slice(-3)'ana' (끝에서 3번째 ~ 끝)
substring()문자열 일부 추출'hello'.substring(1, 3)'el'
split()구분자로 문자열 분할'a,b,c'.split(',')['a', 'b', 'c']
toLowerCase()소문자로 변환'HELLO'.toLowerCase()'hello'
toUpperCase()대문자로 변환'hello'.toUpperCase()'HELLO'
trim()양쪽 공백 제거' hello '.trim()'hello'
replace()패턴/문자열 치환'Hello'.replace('H', 'J')'Jello'
replaceAll()모든 패턴/문자열 치환'aabb'.replaceAll('a', 'x')'xxbb'
repeat()문자열 반복'ha'.repeat(3)'hahaha'
startsWith()시작 여부 확인'hello'.startsWith('he')true
endsWith()끝 여부 확인'hello'.endsWith('lo')true
padStart()targetLength가 되도록 시작에 문자열(padString) 채우기'5'.padStart(3, '0')'005'
'cat'.padStart(10, '123'))'1231231cat'
padEnd()끝에 문자열 채우기'5'.padEnd(3, '0')'500'
match()정규식 패턴과 일치하는 값 찾기'abc123'.match(/\d+/)['123']

참고) slice() 는 뒤에서부터 자를 때 등, substring()은 간단한 작업만!

차이점slice()substring()
음수 인덱스뒤에서부터 셈무조건 0으로 처리
인덱스 순서순서대로 자름순서 바뀌면 자동 교체
유연성더 유연하게 조각 추출간단한 경우 사용 적합

Q3. 평행

https://school.programmers.co.kr/learn/courses/30/lessons/120875
점 네 개의 좌표를 담은 이차원 배열 dots가 다음과 같이 매개변수로 주어집니다.
[[x1, y1], [x2, y2], [x3, y3], [x4, y4]]
주어진 네 개의 점을 두 개씩 이었을 때, 두 직선이 평행이 되는 경우가 있으면 1을 없으면 0을 return 하도록 solution 함수를 완성해보세요.

  • dots의 길이 = 4
  • dots의 원소는 [x, y] 형태이며 x, y는 정수입니다.
  • 0 ≤ x, y ≤ 100
  • 서로 다른 두개 이상의 점이 겹치는 경우는 없습니다.
  • 두 직선이 겹치는 경우(일치하는 경우)에도 1을 return 해주세요.
  • 임의의 두 점을 이은 직선이 x축 또는 y축과 평행한 경우는 주어지지 않습니다.

내 풀이

  • 와 정답률이 낮은 데는 이유가 있었다...
  • 엄청 오래 고민해서 풀었는데 정확성 94.1 나옴.. 🥲
  • 기본 컨셉은 tan 값(기울기)을 구해서 같으면 평행이다 -> 근데 연결 순서가 정해져 있는 게 아니니까 이중 반복을 겁나 돌림
function solution(dots) {
    const tan = [];
    let answer = 0;
    
    for (let i = 3; i > 0; i--) {
        for (let j = 2; j >= 0; j--) {
            if (i === j || i < j) continue;
            let calcTan = Math.abs( (dots[i][1]-dots[j][1]) / 
                                   (dots[i][0]-dots[j][0]));
            tan.push(calcTan);
        }
    }
    
    for (let i = 0; i < tan.length ; i++) {
        for (let j = 0; j < tan.length; j++) {
            if (i === j || i < j) continue;
            answer = (tan[i] === tan[j]) ? 1 : 0
            if (answer === 1) break;
        }
    }
    return answer;
}

오답노트

  • 1) tan 값이 1인 것과 -1인 것은 평행하지 않다... (당연한 소리) -> Math.abs는 불필요함
  • 2) 현재 방법은 모든 점을 두 개씩 연결해서 기울기를 다 계산해보고 중복 기울기만 있으면 평행이라고 판단 -> 실제로 문제 조건은 정확히 두 개의 직선만 만들어야 함
    • dots[0], [1], [2], [3] 에 대해 나올 수 있는 쌍은 세 가지밖에 없음
      • (0,1) -- (2,3)
      • (0,2) -- (1,3)
      • (0,3) -- (1,2)
    • 왜냐하면 두 점을 연결하면 나머지는 자동으로 선택되고, 동시에 같은 점에서 출발한 것을 비교할 수는 없으니까
function solution(dots) {
  // 기울기 구하는 함수
  const getSlope = (a, b) => {
        return (b[1] - a[1])/(b[0] - a[0]);
  };
    
  // 도출 가능한 기울기 값
  let tan = [];
  for (i = 0; i < dots.length; i++) {
    for (j = i+1; j < dots.length; j++ ) {
      let slope = getSlope(dots[i], dots[j]);
      tan.push(slope)
    }
  }

  // 세 가지 케이스 비교
  const answer = (tan[0] === tan[5] || 
                  tan[1] === tan[4] || 
                  tan[2] === tan[3]) ? 1 : 0;
  return answer;
}
    

다른 접근 방식

  • 문제가 어려워서 그런지 대부분 하드코딩이었다..
profile
FE 개발자 지망생입니다..

0개의 댓글