[프로그래머스] 1. 두 개 뽑아서 더하기(Lv.1), 2. 튜플(Lv.2), 3. 이진 변환 반복하기(Lv.3)

손규성·2022년 10월 13일
0

alogrithm

목록 보기
8/22
post-thumbnail

Lv 1: 두 개 뽑아서 더하기✍️


문제 설명

  • 정수 배열 number가 주어졌을 때, 서로 다른 인덱스에 위치한 두 개의 수를 뽑아 더해서 만들 수 있는 모든 수를 새로운 배열에 오름차순으로 담고 반환하는 함수를 작성한다

제한 사항

  • numbers의 길이는 2 이상, 100 이하이다
  • numbers에 포함되어 있는 모든 수는 0 이상 100 이하이다

나의 답안

function solution(numbers) {
  let num = 0;
  let temp = [];

  for(let i = 0; i < numbers.length; i++) {
    num = numbers[i];

    for(let j = 0; j < numbers.length; j++) {
      if(j === i) break;
      
      let sum = num + numbers[j];
      if (temp.length === 0) temp.push(sum);
      else if (!temp.includes(sum)) temp.push(sum);
    }
  }
  return temp.sort((a,b) => a-b);
}

접근 방식

  • 이중for-loop을 통해 numbers 내 두 개의 수를 뽑아내고, 각각의 합을 새로운 배열temp에 담아주는 방식으로 접근했다
  • 문제를 자세히 읽어보면 두 개의 수를 더해서 만들 수 있는 모든 수를 포함하고 있는 배열을 반환하라고 기재되어 있기 때문에 else if(!temp.includes(sum)) 조건을 통해 현재 temp 배열에 존재하지 않는 숫자만 push하도록 했다
  • 첫 제출에서 에러가 떴는데, 이는 두 for-loop의 인덱스, 즉 ij가 겹칠 때도 함수가 수행됐기 때문이었다
  • 두 번째 for-loop에 if(j === i) break;라는 조건을 통해 ij가 똑같으면 두 번째 for-loop이 깨지고 첫 번째 for-loop부터 다시 수행하도록 수정했다

다른 사람의 풀이

function solution(numbers) {
    const temp = []

    for (let i = 0; i < numbers.length; i++) {
        for (let j = i + 1; j < numbers.length; j++) {
            temp.push(numbers[i] + numbers[j])
        }
    }

    const answer = [...new Set(temp)]

    return answer.sort((a, b) => a - b)
}
  • 나의 접근방식과 유사하지만, 나는 두 개의 조건문으로 해결한 걸 set를 사용해서 한줄로 끝냈다
  • 난이도가 높지 않은 문제라도 조금만 더 고민하면 보다 만족스러운 코드를 작성할 수 있는 것 같다


Lv. 2: 튜플✍️


문제 설명

  • (문제 설명은 실제로 상당히 길기 때문에 상단 링크로 접속해서 읽어보는 것 추천)
  • 입출력 예시만 몇개 요약해두자면 →
soutput
"{{2},{2,1},{2,1,3},{2,1,3,4}}"[2, 1, 3, 4]
"{{1,2,3},{2,1},{1,2,4,3},{2}}"[2, 1, 3, 4]
"{{20,111},{111}}"[111, 20]
"{{123}}"[123]
"{{4,2,3},{3},{2,3,4,1},{2,3}}"[3, 2, 4, 1]

제한사항

  • s의 길이는 5 이상 1,000,000 이하
  • s는 숫자와 '{', '}', ',' 로만 이루어져 있다
  • 숫자가 0으로 시작하는 경우는 없다
  • s는 항상 중복되는 원소가 없는 튜플을 올바르게 표현하고 있음
  • s가 표현하는 튜플의 원소는 1 이상 100,000 이하인 자연수이다
  • return 하는 배열의 길이가 1 이상 500 이하인 경우만 입력으로 주어진다

나의 답안

function solution(s) {
    let temp = [], result = [], answer = [], tempStr = '';

    for(let i = 1; i < s.length - 1; i++) {
        if(s[i] === '{' || s[i] === ' ') continue;
        if(s[i] === '}') {
            result.push(temp);
            temp = [];
        }
        if(/\d/.test(s[i]) === true && (s[i + 1] !== ',' || s[i + 1] !== '}')) tempStr += s[i];
        if(/\d/.test(s[i]) === true && (s[i + 1] === ',' || s[i + 1] === '}')) {
            temp.push(tempStr);
            tempStr = '';
        }
    }

    result.sort((a, b) => a.length - b.length);

    for(let i = 0; i < result.length; i++) {
        for(let j = 0; j < result[i].length; j++) {
            if(i === 0) answer.push(Number(result[0][0]));
            else {
                if(answer.includes(Number(result[i][j]))) continue;
                else answer.push(Number(result[i][j]));
            }
        }
    }
    return answer;
}

접근 방식

  • 이전 문제에서 봤던 매개변수와 매우 다르게 생긴, (마치 이중obj처럼 생긴) 매개변수가 주어지기 때문에 헷갈린 문제처럼 느껴질 수 있지만 사실 그렇지 않다
  • s를 탐색하면서 우선 { 혹은 공백이 주어지면 가볍게 무시하고 continue처리한다
  • 대신 }이 주어지면 s에서 한 {}묶음을 다 탐색했다는 뜻이기 때문에 현재까지 누적된 temp배열 자체를 result배열에 push하고 temp배열을 초기화한다
  • 최근 regex에 대해 공부를 시작했고, 자주 사용해보고 익숙해지려고 노력 중이기 때문에 이번 문제에서도 살짝 맛보기로 사용했다 → /\d/.test 를 통해 s[i]가 숫자(digit)일 때를 확인한다
  • 만약 s[i]가 숫자인데 다음 인덱스의 값이 } OR ,이 아니라면, 즉 다음 인덱스 값도 숫자라면 2자리 수 이상의 수라고 판단하고 tempStr에 추가만 한다
  • 반대로 숫자 후 다음 인덱스 값이 숫자가 아닌 경우 현재까지 누적된 tempStr값을 temp배열에 push한다
  • 이중반복문을 통해 temp를 탐색하며 겹치지 않는 숫자를 순서대로 answer배열에 담고 반환한다

아쉬운 점

  • 문제를 풀고 나서 느꼈지만 역시나 이번 문제로 set를 사용해서 훨씬 간결하게 사용할 수 있었을 것 같다
  • 개인적으로 프로그래머스 문제풀이할 때 다른 자료를 찾아보거나 하지 않고 나만의 스타일로, 내가 현재 알고 있는 정보로 풀어보려고 노력하는 편인데, 최근 공부하기 시작한 정규표현식이 잘 기억나지 않아서 아쉬웠다 (아마 조금 더 간결한 코드로, 훨씬 더 빨리 풀이할 수 있는 방법이 존재하지 않을까 싶었다)


Lv. 2: 이진 변환 반복하기✍️


문제 설명

  • 0과 1로 이루어진 문자열 s에 대한 이진 변환을 다음과 같이 정의한다
    1. s의 모든 0을 제거
    2. s의 길이가 c라고 하면, sc를 2진법으로 표현한 문자열로 바꾼다
  • s가 1이 될 때까지 이 과정을 반복하는데, 이때 이진 변화의 횟수와 변환 과정에서 제거된 모든 0의 개수를 각각 배열에 담아 반환한다

제한사항

  • s의 길이는 1 이상 150,000 이하이다
  • s에는 '1'이 최소 하나 이상 포함되어 있다

나의 답안

function solution(s) {
    let answer = [], temp = [], count = 0, countZero = 0, len = 0;
   
    while (len !== 1) {
        for(let i = 0; i < s.length; i++) {
            if (s[i] == 0) countZero++; 
            else if (s[i] == 1) temp.push(s[i]);
        }
        
        count++;
        len = temp.length; 
        s = len.toString(2);
        temp = [];
    }   
    
    answer.push(count);
    answer.push(countZero);

    return answer;
}

접근 방식

  • s를 탐색하면서 s[i]0인 경우 countZero를 증가시켜준다 (총 0이 몇개 지워졌는지 세기 위함)
  • s[i]1인 경우에는 temp라는 새로운 배열에 s[i]를 넣어준다 (추후 length측정하고 이진 변환 후 s값을 업데이트하기 위함)
  • for-loop이 끝난 후에 count를 증가하고 사용한 lentemp는 모두 초기화 해준다
  • s값은 len값으로 변경해주고, len1이 아닌 경우 while문을 통해 모든 과정을 반복한다
  • 반대로 len1이 되어 while문이 깨지게 되면 answer이라는 새로운 배열에 현재까지 누적된 count값과 countZero값을 push해주고 반환한다

아쉬운 점

  • 변수가 정말 너무 많아서 풀면서 이게 과연 최선일까에 대한 의문이 들었다

다른 사람의 풀이

function solution(s) {
    var answer = [0,0];
    while(s.length > 1) {
        answer[0]++;
        answer[1] += (s.match(/0/g)||[]).length;
        s = s.replace(/0/g, '').length.toString(2);
    }
    return answer;
}
  • 역시 최선이 아니었다
  • 사실 당연한건데 한번도 생각해본적이 없는 방법이라 그런가 배열과 인덱스 조합answer[0]++ 하는 걸 보고 신선했다
  • 역시 정규표현식을 자유롭게 사용할 수 있을만큼 공부하는 것이 좋겠다
profile
블로그 이사 → https://sqsung.tistory.com/

0개의 댓글