티스토리 뷰

반응형

 

프로그래머스 - 체육복

 

최대한 피하고 싶었던 이중 for문을 썼다. 제출 후 다른 분들이 푸신 답들을 보며 확 와닿는 게 없다가 밑부분에서 발견했다. 

내가 썼던 이중 반복문을 filter()와 find()를 이용하였고 , shift()를 쓰지 않고 delete라는 연산자를 써서 더 효율적인 코드 같았다. 

 

 


 

풀이과정

 

CS50강의를 들으며 의사 코드이라는 코드 표현 방식을 알게 된 후로 더 적극 활용하게 되었다. 물론 완벽한 형식의 의사 코드는 아니지만..:) 엊그제 예외처리로 애를 먹었던 경험이 있어서 오늘은 모든 경우를 생각하려고 노력했다. 

1. 중복의 제거, lost에있는 번호와 reseve에 있는 번호가 같으면 lost, reserve 둘 다 배열에서 빼준다 (filter)
1.2  lost, reserve 모두 정렬도해준다. 이로 인해 후 연산에서 작은 수부터 반복하기 때문에 최댓값이 구해지게 될 것이다.
2. 현재 체육복있는 사람 let curCount = n - lost.length 1번에서 중복 제거해줬으므로 2번 공식이 성립된다.
3. lost 값 하나하나 +=1 쁠마1씩 해서 있는지 보고 있으면 shift()로 배열에서 제거해준다. 근데 lost에서 i = 0부터 length까지 reseve의 개수만큼 하나씩 검사하는 반복문을 만들어야 함. for가 두 개가 생길 수도..?

 

filter()

filter()로 두 배열의 중복된 값 제거한 새로운 배열 반환하기

의사 코드 1,2번에 해당하는 내용이다. 오름차순대로 해줘야 최댓값이 성립이 되는데 이 부분을 놓치신 분들이 많은 것 같다. 

 

filter()도 reduce()와 같이 활용도가 매우 높은 것 같다. 더 익숙해져야겠다. 

그리고, lostPure, reservePure을 동시 변수 선언하고 같은 작업을 수행하고 싶었는데 찾아봐도 나오지않는다..그건 어려운 걸까..?

  const lostPure = lost
    .filter((num) => !reserve.includes(num))
    .sort((a, b) => a - b);

  const reservePure = reserve
    .filter((num) => !lost.includes(num))
    .sort((a, b) => a - b);

 

 

이 외에도 아래와 같은 방법으로도 중복된 값을 제거할 수 있다. 

  const filtered = lost.filter(function (val) {
    return reserve.indexOf(val) == -1;
  });
  const filtered = lost.filter((lostNum) => {
    let flag = true;
    reserve.forEach((reserveNum) => {
      if (reserveNum === lostNum) {
        flag = false;
      }
    });
    return flag;
  });

 

 

 

 

반복문을 줄이자 - filter() find()

의사 코드에서 3번에 해당되는 부분을 작성했던 코드이다. 

let curCount = n - lostPure.length;

for (let i = 0; i < lostPure.length; i++) {
    for (let j = 0; j < reservePure.length; j++) {
      if (
        reservePure[j] === lostPure[i] - 1 ||
        reservePure[j] === lostPure[i] + 1
      ) {
        curCount++;
        reservePure.shift();
      }
    }
  }

 

 

아래는 다른 분의 코드 중 일부를 참고한 방법이다. filter()로 lost번호의 앞뒤 번호가 맞은 것들만 리턴하고 그 개수를 바로 리턴해주었다. 

 

filter(),  find()

위에서 let curCount = n - lostPure.length; 부분을 쓰지않고 바로 변수선언을 length로 해주었다.
filter()와 find()를 통해 더 효율적인 알고리즘이 되었다. 
 
예전에도 find()로 비슷하게 했던 것 같은데 이번 문제 풀 때는 find()를 써야겠다는 생각을 못했다. 연습이 많이 필요할 듯 하다..
 
 
 
 const curCount = lostPure.filter((a) => {
    return reservePure.find((b, i) => {
      const has = b === a - 1 || b === a + 1;
      if (has) {
        delete reservePure[i];
      }
      return has;
    });
  }).length;
  return n - (lostPure.length - curCount);

 

속도 차이ㅠㅠ

 

 


 

 

전체 답안 

function solution(n, lost, reserve) {

  const lostPure = lost
    .filter((num) => !reserve.includes(num))
    .sort((a, b) => a - b);

  const reservePure = reserve
    .filter((num) => !lost.includes(num))
    .sort((a, b) => a - b);

  console.log(lostPure, reservePure);

  let curCount = n - lostPure.length;

  for (let i = 0; i < lostPure.length; i++) {
    for (let j = 0; j < reservePure.length; j++) {
      if (
        reservePure[j] === lostPure[i] - 1 ||
        reservePure[j] === lostPure[i] + 1
      ) {
        curCount++;
        reservePure.shift();
      }
    }
  }
  return curCount;
}

 

 

제출 후 수정한 답안 

function solution(n, lost, reserve) {
  const lostPure = lost
    .filter((num) => !reserve.includes(num))
    .sort((a, b) => a - b);

  const reservePure = reserve
    .filter((num) => !lost.includes(num))
    .sort((a, b) => a - b);
    
 const curCount = lostPure.filter((a) => {
    return reservePure.find((b, i) => {
      const has = b === a - 1 || b === a + 1;
      if (has) {
        delete reservePure[i];
      }
      return has;
    });
  }).length;
  return n - (lostPure.length - curCount);
}

 

 



 

반응형