DEVELOP
article thumbnail
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

GitHub - cjy00n/coding-test

Contribute to cjy00n/coding-test development by creating an account on GitHub.

github.com


가장 가까운 같은 글자 #142086


문제 설명
문자열 s가 주어졌을 때, s의 각 위치마다 자신보다 앞에 나왔으면서, 자신과 가장 가까운 곳에 있는 같은 글자가 어디 있는지 알고 싶습니다.
예를 들어, s="banana"라고 할 때,  각 글자들을 왼쪽부터 오른쪽으로 읽어 나가면서 다음과 같이 진행할 수 있습니다.

b는 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.
a는 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.
n은 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.
a는 자신보다 두 칸 앞에 a가 있습니다. 이는 2로 표현합니다.
n도 자신보다 두 칸 앞에 n이 있습니다. 이는 2로 표현합니다.
a는 자신보다 두 칸, 네 칸 앞에 a가 있습니다. 이 중 가까운 것은 두 칸 앞이고, 이는 2로 표현합니다.
따라서 최종 결과물은 [-1, -1, -1, 2, 2, 2]가 됩니다.

문자열 s이 주어질 때, 위와 같이 정의된 연산을 수행하는 함수 solution을 완성해주세요.

제한사항
1 ≤ s의 길이 ≤ 10,000
s은 영어 소문자로만 이루어져 있습니다.


입출력 예
s result
"banana" [-1, -1, -1, 2, 2, 2]
"foobar" [-1, -1, 1, -1, -1, -1]

 

▼ 나의 풀이

function solution(s) {
  let answer = [];
  let history = [];
  [...s].map((c, i) => {
    if (!history.includes(c)) answer.push(-1);
    else answer.push(i - history.lastIndexOf(c));
    history.push(c);
  });
  return answer;
}

=> 배열에 push를 해야하고, includes로 확인(배열 전체에서 찾아야 함), lastIndexOf(배열 순회 필요) 이므로 문제는 해결되지만 비효율적이라고 할 수 있다. 

 

▼ hash 형식의 객체를 사용한 풀이

function solution(s) {
  const hash = {};
  return [...s].map((c, i) => {
    let result = hash[c] !== undefined ? i - hash[c] : -1;
    hash[c] = i;
    return result;
  });
}

=> 배열 대신에 객체를 이용해서 해당 문자의 index값을 확인할 수 있도록 했다. 

=> 배열 전용 내장 함수를 거의 사용하지 않아서 좋은 것 같다. 


콜라 문제 #132267


문제 설명
오래전 유행했던 콜라 문제가 있습니다. 콜라 문제의 지문은 다음과 같습니다.

정답은 아무에게도 말하지 마세요.

콜라 빈 병 2개를 가져다주면 콜라 1병을 주는 마트가 있다. 빈 병 20개를 가져다주면 몇 병을 받을 수 있는가?

단, 보유 중인 빈 병이 2개 미만이면, 콜라를 받을 수 없다.

문제를 풀던 상빈이는 콜라 문제의 완벽한 해답을 찾았습니다. 상빈이가 푼 방법은 아래 그림과 같습니다. 우선 콜라 빈 병 20병을 가져가서 10병을 받습니다. 받은 10병을 모두 마신 뒤, 가져가서 5병을 받습니다. 5병 중 4병을 모두 마신 뒤 가져가서 2병을 받고, 또 2병을 모두 마신 뒤 가져가서 1병을 받습니다. 받은 1병과 5병을 받았을 때 남은 1병을 모두 마신 뒤 가져가면 1병을 또 받을 수 있습니다. 이 경우 상빈이는 총 10 + 5 + 2 + 1 + 1 = 19병의 콜라를 받을 수 있습니다.


문제를 열심히 풀던 상빈이는 일반화된 콜라 문제를 생각했습니다. 이 문제는 빈 병 a개를 가져다주면 콜라 b병을 주는 마트가 있을 때, 빈 병 n개를 가져다주면 몇 병을 받을 수 있는지 계산하는 문제입니다. 기존 콜라 문제와 마찬가지로, 보유 중인 빈 병이 a개 미만이면, 추가적으로 빈 병을 받을 순 없습니다. 상빈이는 열심히 고심했지만, 일반화된 콜라 문제의 답을 찾을 수 없었습니다. 상빈이를 도와, 일반화된 콜라 문제를 해결하는 프로그램을 만들어 주세요.

콜라를 받기 위해 마트에 주어야 하는 병 수 a, 빈 병 a개를 가져다 주면 마트가 주는 콜라 병 수 b, 상빈이가 가지고 있는 빈 병의 개수 n이 매개변수로 주어집니다. 상빈이가 받을 수 있는 콜라의 병 수를 return 하도록 solution 함수를 작성해주세요.

제한사항
1 ≤ b < a ≤ n ≤ 1,000,000
정답은 항상 int 범위를 넘지 않게 주어집니다.


입출력 예
a b n result
2 1 20 19
3 1 20 9

 

▼ 나의 풀이 

function solution(a, b, n) {
  var answer = 0;
  while (n >= a) {
    let d = parseInt(n / a); // 찬스 수
    answer += d * b; // 찬스로 받는 병 수
    n = n - a * d + d * b; // 현재 가지고 있는 병 수
  }
  return answer;
}
  • 받을 수 있는 찬스 수를 d로 정의 
  • 그 찬스로부터 받는 병 수는 answer
  • 현재 가지고 있는 병 수는 n 

추억 점수 #176963


문제 설명
사진들을 보며 추억에 젖어 있던 루는 사진별로 추억 점수를 매길려고 합니다. 사진 속에 나오는 인물의 그리움 점수를 모두 합산한 값이 해당 사진의 추억 점수가 됩니다. 예를 들어 사진 속 인물의 이름이 ["may", "kein", "kain"]이고 각 인물의 그리움 점수가 [5점, 10점, 1점]일 때 해당 사진의 추억 점수는 16(5 + 10 + 1)점이 됩니다. 다른 사진 속 인물의 이름이 ["kali", "mari", "don", "tony"]이고 ["kali", "mari", "don"]의 그리움 점수가 각각 [11점, 1점, 55점]]이고, "tony"는 그리움 점수가 없을 때, 이 사진의 추억 점수는 3명의 그리움 점수를 합한 67(11 + 1 + 55)점입니다.

그리워하는 사람의 이름을 담은 문자열 배열 name, 각 사람별 그리움 점수를 담은 정수 배열 yearning, 각 사진에 찍힌 인물의 이름을 담은 이차원 문자열 배열 photo가 매개변수로 주어질 때, 사진들의 추억 점수를 photo에 주어진 순서대로 배열에 담아 return하는 solution 함수를 완성해주세요.

제한사항
3 ≤ name의 길이 = yearning의 길이≤ 100
3 ≤ name의 원소의 길이 ≤ 7
name의 원소들은 알파벳 소문자로만 이루어져 있습니다.
name에는 중복된 값이 들어가지 않습니다.
1 ≤ yearning[i] ≤ 100
yearning[i]는 i번째 사람의 그리움 점수입니다.
3 ≤ photo의 길이 ≤ 100
1 ≤ photo[i]의 길이 ≤ 100
3 ≤ photo[i]의 원소(문자열)의 길이 ≤ 7
photo[i]의 원소들은 알파벳 소문자로만 이루어져 있습니다.
photo[i]의 원소들은 중복된 값이 들어가지 않습니다.


입출력 예
name yearning photo result
["may", "kein", "kain", "radi"] [5, 10, 1, 3] [["may", "kein", "kain", "radi"],["may", "kein", "brin", "deny"], ["kon", "kain", "may", "coni"]] [19, 15, 6]
["kali", "mari", "don"] [11, 1, 55] [["kali", "mari", "don"], ["pony", "tom", "teddy"], ["con", "mona", "don"]] [67, 0, 55]
["may", "kein", "kain", "radi"] [5, 10, 1, 3] [["may"],["kein", "deny", "may"], ["kon", "coni"]] [5, 15, 0]

 

▼ map을 두 번돌린 나의 풀이 

function solution(name, yearning, photo) {
  return photo.map((p) => {
    let score = 0;
    p.map((n) => {
      if (name.indexOf(n) != -1) score += yearning[name.indexOf(n)];
    });
    return score;
  });
}

▼ reduce와 nullish coalescing operator를 사용한 풀이

function solution(name, yearning, photo) {
  return photo.map((arr) =>
    arr.reduce((a, c) => (a += yearning[name.indexOf(c)] ?? 0), 0)
  );
}
  • reduce함수를 왜 떠올리지 못했을까
  • nullish coalescing operator를 이제 제대로 알게 되었다. 
  • nullish coalescing operator는 첫 번째 인자가 null 또는 undefined인 경우 두 번째 인자를 반환한다. 

명예의 전당 (1)  #138477


문제 설명
"명예의 전당"이라는 TV 프로그램에서는 매일 1명의 가수가 노래를 부르고, 시청자들의 문자 투표수로 가수에게 점수를 부여합니다. 매일 출연한 가수의 점수가 지금까지 출연 가수들의 점수 중 상위 k번째 이내이면 해당 가수의 점수를 명예의 전당이라는 목록에 올려 기념합니다. 즉 프로그램 시작 이후 초기에 k일까지는 모든 출연 가수의 점수가 명예의 전당에 오르게 됩니다. k일 다음부터는 출연 가수의 점수가 기존의 명예의 전당 목록의 k번째 순위의 가수 점수보다 더 높으면, 출연 가수의 점수가 명예의 전당에 오르게 되고 기존의 k번째 순위의 점수는 명예의 전당에서 내려오게 됩니다.

이 프로그램에서는 매일 "명예의 전당"의 최하위 점수를 발표합니다. 예를 들어, k = 3이고, 7일 동안 진행된 가수의 점수가 [10, 100, 20, 150, 1, 100, 200]이라면, 명예의 전당에서 발표된 점수는 아래의 그림과 같이 [10, 10, 10, 20, 20, 100, 100]입니다.


명예의 전당 목록의 점수의 개수 k, 1일부터 마지막 날까지 출연한 가수들의 점수인 score가 주어졌을 때, 매일 발표된 명예의 전당의 최하위 점수를 return하는 solution 함수를 완성해주세요.

제한사항
3 ≤ k ≤ 100
7 ≤ score의 길이 ≤ 1,000
0 ≤ score[i] ≤ 2,000
입출력 예
k score result
3 [10, 100, 20, 150, 1, 100, 200] [10, 10, 10, 20, 20, 100, 100]
4 [0, 300, 40, 300, 20, 70, 150, 50, 500, 1000] [0, 0, 0, 0, 20, 40, 70, 70, 150, 300]

 

▼ 나의 풀이

const solution = (k, score) =>
  score.map((v, i) =>
    score
      .slice(0, i + 1)
      .sort((a, b) => b - a)
      .slice(0, k)
      .at(-1)
  );
  • score에 map을 돌려서 각 날짜에 맞게 slice하고,  내림차순으로 정렬한다. 
  • 명예의 전당에 올라가는 점수는 최대 k개 이므로, 다시 k개만큼 slice한다. 
  • 명예의 전당 중 가장 마지막 값이 최저 점수이므로 at으로 마지막 값을 리턴한다. 
  • score의 길이가 길어질 수록 시간이 매우 오래 걸리게 된다. 

▼ reduce를 이용한 풀이 

const solution = (k, score) => {
  const best = [];
  return score.reduce((a, c) => {
    if (best.length < k) {
      best.push(c);
      best.sort((a, b) => a - b);
    } else {
      best.push(c);
      best.sort((a, b) => a - b);
      best.shift();
    }
    a.push(best[0]);
    return a;
  }, []);
};
  • 명예의 전당 점수들만 관리하는 best 배열을 만든다. 
  • k번째 일 까자는 각 날의 점수들을 push한 후 오름차순으로 sort한 것이 명예의 전당에 오르는 점수들이다.
  • k번째 일 이후에는 각 날의 점수를 push한 후 오름차순으로 sort하는 것까지는 똑같으나,하나를 빼주어야 하므로, 가장 작은 점수(가장 앞)을 빼도록 shift()를 해준다.
  • 현재 명예의 전당 점수 배열(best)는 오름차순으로 되어있으므로 최저점수는 가장 첫번째 값이므로, a에 push해준다.
  • 최종적으로 a를 return한다. 

2016년 #12901


문제 설명
2016년 1월 1일은 금요일입니다. 2016년 a월 b일은 무슨 요일일까요? 두 수 a ,b를 입력받아 2016년 a월 b일이 무슨 요일인지 리턴하는 함수, solution을 완성하세요. 요일의 이름은 일요일부터 토요일까지 각각 SUN,MON,TUE,WED,THU,FRI,SAT

입니다. 예를 들어 a=5, b=24라면 5월 24일은 화요일이므로 문자열 "TUE"를 반환하세요.

제한 조건
2016년은 윤년입니다.
2016년 a월 b일은 실제로 있는 날입니다. (13월 26일이나 2월 45일같은 날짜는 주어지지 않습니다)


입출력 예
a b result
5 24 "TUE"

 

▼ 나의 풀이 

function solution(a, b) {
  const days = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
  const daysOfMonth = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  let d = b - 1 + days.indexOf("FRI");
  for (let i = 0; i < a - 1; i++) {
    d += daysOfMonth[i];
  }
  return days[d % 7];
}

폰켓몬 #1845


문제 설명
당신은 폰켓몬을 잡기 위한 오랜 여행 끝에, 홍 박사님의 연구실에 도착했습니다. 홍 박사님은 당신에게 자신의 연구실에 있는 총 N 마리의 폰켓몬 중에서 N/2마리를 가져가도 좋다고 했습니다.
홍 박사님 연구실의 폰켓몬은 종류에 따라 번호를 붙여 구분합니다. 따라서 같은 종류의 폰켓몬은 같은 번호를 가지고 있습니다. 예를 들어 연구실에 총 4마리의 폰켓몬이 있고, 각 폰켓몬의 종류 번호가 [3번, 1번, 2번, 3번]이라면 이는 3번 폰켓몬 두 마리, 1번 폰켓몬 한 마리, 2번 폰켓몬 한 마리가 있음을 나타냅니다. 이때, 4마리의 폰켓몬 중 2마리를 고르는 방법은 다음과 같이 6가지가 있습니다.

첫 번째(3번), 두 번째(1번) 폰켓몬을 선택
첫 번째(3번), 세 번째(2번) 폰켓몬을 선택
첫 번째(3번), 네 번째(3번) 폰켓몬을 선택
두 번째(1번), 세 번째(2번) 폰켓몬을 선택
두 번째(1번), 네 번째(3번) 폰켓몬을 선택
세 번째(2번), 네 번째(3번) 폰켓몬을 선택
이때, 첫 번째(3번) 폰켓몬과 네 번째(3번) 폰켓몬을 선택하는 방법은 한 종류(3번 폰켓몬 두 마리)의 폰켓몬만 가질 수 있지만, 다른 방법들은 모두 두 종류의 폰켓몬을 가질 수 있습니다. 따라서 위 예시에서 가질 수 있는 폰켓몬 종류 수의 최댓값은 2가 됩니다.
당신은 최대한 다양한 종류의 폰켓몬을 가지길 원하기 때문에, 최대한 많은 종류의 폰켓몬을 포함해서 N/2마리를 선택하려 합니다. N마리 폰켓몬의 종류 번호가 담긴 배열 nums가 매개변수로 주어질 때, N/2마리의 폰켓몬을 선택하는 방법 중, 가장 많은 종류의 폰켓몬을 선택하는 방법을 찾아, 그때의 폰켓몬 종류 번호의 개수를 return 하도록 solution 함수를 완성해주세요.

제한사항
nums는 폰켓몬의 종류 번호가 담긴 1차원 배열입니다.
nums의 길이(N)는 1 이상 10,000 이하의 자연수이며, 항상 짝수로 주어집니다.
폰켓몬의 종류 번호는 1 이상 200,000 이하의 자연수로 나타냅니다.
가장 많은 종류의 폰켓몬을 선택하는 방법이 여러 가지인 경우에도, 선택할 수 있는 폰켓몬 종류 개수의 최댓값 하나만 return 하면 됩니다.

 

입출력 예
nums result
[3,1,2,3] 2
[3,3,3,2,2,4] 3
[3,3,3,2,2,2] 2

 

▼ 나의 풀이

function solution(nums) {
  const num = nums.length / 2;
  nums = [...new Set(nums)];
  return num >= nums.length ? nums.length : num;
}
  • new Set으로 중복 제거하는 거 아주 유용하다 .....!! 

카드 뭉치 #159994


문제 설명
코니는 영어 단어가 적힌 카드 뭉치 두 개를 선물로 받았습니다. 코니는 다음과 같은 규칙으로 카드에 적힌 단어들을 사용해 원하는 순서의 단어 배열을 만들 수 있는지 알고 싶습니다.

원하는 카드 뭉치에서 카드를 순서대로 한 장씩 사용합니다.
한 번 사용한 카드는 다시 사용할 수 없습니다.
카드를 사용하지 않고 다음 카드로 넘어갈 수 없습니다.
기존에 주어진 카드 뭉치의 단어 순서는 바꿀 수 없습니다.
예를 들어 첫 번째 카드 뭉치에 순서대로 ["i", "drink", "water"], 두 번째 카드 뭉치에 순서대로 ["want", "to"]가 적혀있을 때 ["i", "want", "to", "drink", "water"] 순서의 단어 배열을 만들려고 한다면 첫 번째 카드 뭉치에서 "i"를 사용한 후 두 번째 카드 뭉치에서 "want"와 "to"를 사용하고 첫 번째 카드뭉치에 "drink"와 "water"를 차례대로 사용하면 원하는 순서의 단어 배열을 만들 수 있습니다.

문자열로 이루어진 배열 cards1, cards2와 원하는 단어 배열 goal이 매개변수로 주어질 때, cards1과 cards2에 적힌 단어들로 goal를 만들 있다면 "Yes"를, 만들 수 없다면 "No"를 return하는 solution 함수를 완성해주세요.

제한사항
1 ≤ cards1의 길이, cards2의 길이 ≤ 10
1 ≤ cards1[i]의 길이, cards2[i]의 길이 ≤ 10
cards1과 cards2에는 서로 다른 단어만 존재합니다.
2 ≤ goal의 길이 ≤ cards1의 길이 + cards2의 길이
1 ≤ goal[i]의 길이 ≤ 10
goal의 원소는 cards1과 cards2의 원소들로만 이루어져 있습니다.
cards1, cards2, goal의 문자열들은 모두 알파벳 소문자로만 이루어져 있습니다.


입출력 예
cards1 cards2 goal result
["i", "drink", "water"] ["want", "to"] ["i", "want", "to", "drink", "water"] "Yes"
["i", "water", "drink"] ["want", "to"] ["i", "want", "to", "drink", "water"] "No"

 

▼ 나의 풀이 

function solution(cards1, cards2, goal) {
  var answer = "Yes";
  for (let i = 0; i < goal.length; i++) {
    let a = cards1.indexOf(goal[i]);
    let b = cards2.indexOf(goal[i]);
    if (a != 0 && b != 0) {
      answer = "No";
      break;
    } else if (a == 0) cards1.shift();
    else if (b == 0) cards2.shift();
  }
  return answer;
}
  • 처음에 '카드를 사용하지 않고 다음 카드로 넘어갈 수 없습니다.' 이 조건을 제대로 안봐서 index로 받아서 쓰다가 나중에 깨닫고 아래 부분만 수정해서 지저분한 코드가 되었다.
  • 모든 값들을 확인하므로 실행 시간이 매우 오래걸리게 된다. (indexOf ) 
  • 그래도 shift 사용한 건 좋은 접근이었다.
function solution(cards1, cards2, goal) {
  for (const s of goal) {
    if (cards1[0] == s) cards1.shift();
    else if (cards2[0] == s) cards2.shift();
    else return "No";
  }
  return "Yes";
}
  • 난 for문을 항상 변수 선언해서 하려는 고정관념?이 있는 것 같다. 저렇게 하는 것이 훨씬 깔끔하고 직관적이다. 
  • 각 배열들의 첫번째 값만 확인하면 된다. 
  • 두 배열의 첫번째 값들이 모두 아닐 때는 "No"를 리턴하고 종료. 

과일 장수 #135808


문제 설명
과일 장수가 사과 상자를 포장하고 있습니다. 사과는 상태에 따라 1점부터 k점까지의 점수로 분류하며, k점이 최상품의 사과이고 1점이 최하품의 사과입니다. 사과 한 상자의 가격은 다음과 같이 결정됩니다.

한 상자에 사과를 m개씩 담아 포장합니다.
상자에 담긴 사과 중 가장 낮은 점수가 p (1 ≤ p ≤ k)점인 경우, 사과 한 상자의 가격은 p * m 입니다.
과일 장수가 가능한 많은 사과를 팔았을 때, 얻을 수 있는 최대 이익을 계산하고자 합니다.(사과는 상자 단위로만 판매하며, 남는 사과는 버립니다)

예를 들어, k = 3, m = 4, 사과 7개의 점수가 [1, 2, 3, 1, 2, 3, 1]이라면, 다음과 같이 [2, 3, 2, 3]으로 구성된 사과 상자 1개를 만들어 판매하여 최대 이익을 얻을 수 있습니다.

(최저 사과 점수) x (한 상자에 담긴 사과 개수) x (상자의 개수) = 2 x 4 x 1 = 8
사과의 최대 점수 k, 한 상자에 들어가는 사과의 수 m, 사과들의 점수 score가 주어졌을 때, 과일 장수가 얻을 수 있는 최대 이익을 return하는 solution 함수를 완성해주세요.

제한사항
3 ≤ k ≤ 9
3 ≤ m ≤ 10
7 ≤ score의 길이 ≤ 1,000,000
1 ≤ score[i] ≤ k
이익이 발생하지 않는 경우에는 0을 return 해주세요.


입출력 예
k m score result
3 4 [1, 2, 3, 1, 2, 3, 1] 8
4 3 [4, 1, 2, 2, 4, 4, 4, 4, 1, 2, 4, 2] 33

 

▼ 나의 풀이 

function solution(k, m, score) {
  var answer = 0;
  score.sort((a, b) => a - b);
  const num = score.length;
  for (let i = 0; i < num % m; i++) score.shift();
  for (let i = 0; i < score.length; i += m)
    score[i] >= k ? (answer += k * m) : (answer += score[i] * m);

  return answer;
}
  • slice를 쓸까하다가 shift를 썼는데, slice를 썼어야 했다. 
  • 이 문제에서 k를 왜 준거지 ? 

▼ slice를 이용한 풀이

function solution(k, m, score) {
  let answer = 0;
  let sortedScore = score.sort((a, b) => a - b).slice(score.length % m);
  for (let i = 0; i < sortedScore.length; i += m) answer += sortedScore[i] * m;
  return answer;
}

✓ slice() 에 시작값만 주면, 시작값부터 끝까지를 잘라내어 복사한다.


모의고사 #42840


문제 설명
수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍습니다.

1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ...
2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5, ...
3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, ...

1번 문제부터 마지막 문제까지의 정답이 순서대로 들은 배열 answers가 주어졌을 때, 가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 return 하도록 solution 함수를 작성해주세요.

제한 조건
시험은 최대 10,000 문제로 구성되어있습니다.
문제의 정답은 1, 2, 3, 4, 5중 하나입니다.
가장 높은 점수를 받은 사람이 여럿일 경우, return하는 값을 오름차순 정렬해주세요.


입출력 예
answers return
[1,2,3,4,5] [1]
[1,3,2,4,2] [1,2,3]

 

▼ 나의풀이

function solution(answers) {
  let score = [0, 0, 0];
  for (let i = 0; i < answers.length; i++) {
    if (answers[i] == (i % 5) + 1) score[0]++;
    if (answers[i] == [2, 1, 2, 3, 2, 4, 2, 5][i % 8]) score[1]++;
    if (answers[i] == [3, 3, 1, 1, 2, 2, 4, 4, 5, 5][i % 10]) score[2]++;
  }

  return score.reduce((a, v, i) => {
    if (v == Math.max(...score)) a.push(i + 1);
    return a;
  }, []);
}

▼ filter()를 사용한 풀이 

function solution(answers) {
  var answer = [];
  let a1 = [1, 2, 3, 4, 5];
  let a2 = [2, 1, 2, 3, 2, 4, 2, 5];
  let a3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5];

  let s1 = answers.filter((a, i) => a == a1[i % a1.length]).length;
  let s2 = answers.filter((a, i) => a == a2[i % a2.length]).length;
  let s3 = answers.filter((a, i) => a == a3[i % a3.length]).length;

  let max = Math.max(s1, s2, s3);
  if (s1 == max) answer.push(1);
  if (s2 == max) answer.push(2);
  if (s3 == max) answer.push(3);

  return answer;
}
  • 두 풀이에서 접근방식은 비슷하다고 생각하는데, 시간 측면에서 아래 것이 훨씬 좋았다. 
  • 변수 사용을 줄이려는 쓸데 없는 생각으로 배열을 if 문 안에서 사용했는데, 미리 선언하는 것이 더 좋을 것 같다. 
  • filter와 for문의 시간복잡도는 같다. 
  • 나는 점수 변수에 1씩 추가하는 식으로 했는데, 어차피 문제마다 점수는 같으므로 filter 후 길이만 구하면 된다. 
  • max값도 미리 선언 후 사용하는 것이 더 효율적이다. (시간복잡도가 O(N)이기에 ) 
  • 학생 수가 3명뿐이기 때문에 굳이 reduce를 쓰지 않고 하나씩 if문으로 비교후 push해도 된다. 

소수 만들기 #12977


문제 설명
주어진 숫자 중 3개의 수를 더했을 때 소수가 되는 경우의 개수를 구하려고 합니다. 숫자들이 들어있는 배열 nums가 매개변수로 주어질 때, nums에 있는 숫자들 중 서로 다른 3개를 골라 더했을 때 소수가 되는 경우의 개수를 return 하도록 solution 함수를 완성해주세요.

제한사항
nums에 들어있는 숫자의 개수는 3개 이상 50개 이하입니다.
nums의 각 원소는 1 이상 1,000 이하의 자연수이며, 중복된 숫자가 들어있지 않습니다.


입출력 예
nums result


[1,2,3,4] 1
[1,2,7,6,4] 4

 

▼ 나의 풀이 

function solution(nums) {
  var answer = 0;
  for (let i = 0; i < nums.length - 2; i++) {
    for (let j = i + 1; j < nums.length - 1; j++) {
      for (let k = j + 1; k < nums.length; k++) {
        let sum = nums[i] + nums[j] + nums[k];
        if (isPrime(sum)) answer++;
      }
    }
  }
  return answer;
}

const isPrime = (n) => {
  if (n == 2) return true;
  else if (n == 1 || n % 2 == 0) return false;
  else {
    for (let i = 3; i < n / 2; i++) if (n % i == 0) return false;
    return true;
  }
};

▼ isPrime 함수 수정 

function solution(nums) {
  var answer = 0;
  for (let i = 0; i < nums.length - 2; i++) {
    for (let j = i + 1; j < nums.length - 1; j++) {
      for (let k = j + 1; k < nums.length; k++)
        if (isPrime(nums[i] + nums[j] + nums[k])) answer++;
    }
  }
  return answer;
}

const isPrime = (n) => {
  for (let i = 2; i <= Math.sqrt(n); i++) if (n % i == 0) return false;
  return true;
};
  • 소수 판별할 때 제곱근까지만 구하면 된다는 것을 까먹고 있었다 !
  • 그리고 굳이 2인지 판단하지 않아도, n이 2면 for문을 진입하지 않기 때문에 true가 된다.
  • for문을 3번 돌리는 것이 딱 보기에는 비효율적으로 보이지만 저것말고는 방법이 없다. 
profile

DEVELOP

@JUNGY00N