TIL 20230410 알고리즘 문제풀이
function solution(n) {
let arr = []
let pow = []
let acul = []
while (true) {
arr.push(n % 3)
n = Math.floor(n / 3)
if (n / 3 === 0) {
break
}
}
for (j = arr.length - 1; j >= 0; j--) {
pow.push(j)
}
for(i=0; i < arr.length; i++){
acul.push(arr[i] * Math.pow(3,pow[i]))
}
return acul.reduce((a,b)=> a+b)
}
console.log(solution(45))
console.log(solution(125))
# 숫자를 3진법으로 변환하는 과정은 다음과 같다.
1. 45 / 3 = 15 ... 0
2. 몫을 다시 3으로 나눈다. 15 / 3 = 5 ... 0
3. 몫을 다시 3으로 나눈다. 5 / 3 = 1 ... 2
4. 몫을 다시 3으로 나눈다. 1 / 3 = 0 ... 1
위와 같이 몫이 0이 될때까지 나누고 0이 된다면
이때 나머지를 거꾸로 뒤집으면 1200이 되는데 이 값이 45를 3진법으로 변환한 수이다.
먼저 n를 3으로 나눈 나머지를 arr에 넣는다. 그 후 n을 3으로 나눈 몫을 n에 다시 할당한다. 이렇게 되면 첫번째 반복땐 45를 3으로 나눈 나머지(= 0)을 arr에 넣고 45를 3으로 나눈 몫을 n에 다시 할당한다. 그럼 다음 반복땐 n에 할당한 데이터는 15가 된다.
계속 이렇게 반복하다가(while가 true이기 때문에 계속 반복), 만약 n / 3 === 0 이 된다면(3진법으로 변환하려면 몫이 0이 될때까지 나눠야하기 때문) 반복문을 break를 통해 끝내게 했다. 이때 arr엔 [0,0,2,1] 값이 할당된다.
# 1200을 다시 10진법으로 구하는 과정은 다음과 같다.
1. 첫째 자리(오른쪽부터 세어 첫 번째) : 0 * 3^3 = 0
2. 둘째 자리 : 0 * 3^2 = 0
3. 셋째 자리 : 2 * 3^1 = 6
4. 넷째 자리(가장 왼쪽) : 1 * 3^0 = 1
5. 모든 값을 더한다 : 0 + 0 + 6 + 1 = 7
pow 배열에 3진수 자리수의 지수값을 구하기 위하여 반복문을 돌린다. n에 45가 들어온다고 가정했을때 pow 배열에는 [3,2,1,0] 값이 저장된다.
반복문을 통해 arr[i] * Math.pow(3, pow[i]) 을 반복 실행하게 했는데, Math.pow(밑, 지수) 형태이다. 즉, 3을 pow[i] 만큼 제곱한다는 의미이다. arr의 각 요소와 곱해준 값을 acul 배열에 할당 후 모든 값을 더해야 하므로 reduce((a,b) => a+b)을 사용해 리턴했다.
# 다른 사람의 풀이
const solution = (n) => {
return parseInt([...n.toString(3)].reverse().join(""), 3);
}
n.toString(3) : 주어진 양의 정수 3을 3진법으로 문자열로 변환한다.
...n.toString(3) : 주어진 양의 정수 3을 3진법으로 문자열로 변환한 후 스프레드 문법을 통해 배열로 리턴한다.
reverse() : 배열의 순서를 뒤집는다.
join("") : 배열을 문자열로 변환한다.
parseInt(..., 3) : 이어진 3진법 문자열을 10진법 숫자로 변환한다.
function solution(sizes) {
let w = []
let h = []
let z = []
for(i=0; i < sizes.length; i++){
w.push(sizes[i].sort((a,b) => b - a))
}
for(i=0; i< sizes.length; i++){
h.push(w[i][0])
}
let hMax = Math.max(...h)
for(i=0; i<sizes.length; i++){
z.push(w[i][1])
}
let zMax = Math.max(...z)
return hMax * zMax
}
console.log(solution([[60, 50], [30, 70], [60, 30], [80, 40]]))
console.log(solution([[10, 7], [12, 3], [8, 15], [14, 7], [5, 15]]))
console.log(solution([[14, 4], [19, 6], [6, 16], [18, 7], [7, 11]]))
먼저 배열내의 배열을 내림차순으로 정렬했다. 첫번째 반복문이 끝나면 w에는 [ [ 60, 50 ], [ 70, 30 ], [ 60, 30 ], [ 80, 40 ] ] 값이 할당되게 된다.
빈 배열 h에 각 배열의 0번째 인덱스 요소를 넣어줬다. 이때 h에는 [ 60, 70, 60, 80 ] 값이 담기게 된다.
hMax 변수에 배열 h의 가장 큰 수를 할당해줬다.
다시 내림차순으로 정렬한 배열 w의 1번째 인덱스 요소들을 빈 배열 z에 할당한다. 이때 z에는 [ 50, 30, 30, 40 ] 값이 할당된다.
그후 배열 z의 가장 큰 수를 zMax에 할당한다.
마지막으로 hMax와 zMax를 곱한 값을 리턴한다.
# 다른 사람의 풀이
function solution(sizes) {
const rotated = sizes.map(([w, h]) => w < h ? [h, w] : [w, h]);
let maxSize = [0, 0];
rotated.forEach(([w, h]) => {
if (w > maxSize[0]) maxSize[0] = w;
if (h > maxSize[1]) maxSize[1] = h;
})
return maxSize[0]*maxSize[1];
}
map() 함수를 사용해 매개변수로 받은 sizes의 내부의 각 배열을 순차적으로 넣어서 [h, w] 형태로 만들어줬는데 h와 w 값을 비교하여 h에 더 큰 값이 오도록 정렬하여 리턴하고 rotated에 할당했다. 즉, 이 과정은 내 풀이에서 sort 메소드를 사용해 내림차순 정렬을 해준 것과 같다. 그러나 내 풀이에선 배열 요소를 하나씩 개별로 나눠서 저장했으나, 이 풀이에선 배열을 해체하지 않고 원래의 틀 그대로 리턴한다.
maxSize 변수에 [0, 0] 형태로 초기화 시킨다.
forEach() 반복문과 조건문을 사용해 만약 rotated 배열의 w가 maxSize의 0 번째 인덱스보다 크다면 maxSize의 0번째 인덱스에는 w값이 재할당 되게 했고, 마찬가지로 h가 maxSize의 1번째 인덱스보다 크다면 maxSize의 1번째 인덱스는 h 값이 재할당 되게 해서
rotated 값중 가장 큰 w와 h 값이 maxSize의 0번째 인덱스와 1번째 인덱스에 할당하게 했다.
마지막으로 가장 큰 값을 골라낸 maxSize의 0번째 인덱스와 1번째 인덱스를 곱해줘서 리턴한다.
function solution(arr) {
let result = []
for (i = 1; i < arr.length; i++) {
if(arr[i] !== arr[i - 1]){
result.push(arr[i-1])
}
}
result.push(arr[arr.length - 1])
return result
}
console.log(solution([1, 1, 3, 3, 0, 1, 1]))
console.log(solution([4, 4, 4, 3, 3]))
반복문을 사용해 i의 초기값을 1로 설정했다.
1번째 반복 : 만약 arr의 1번째 인덱스(1)와 arr의 0번째 인덱스(1)가 같지 않다면 arr의 0번째 인덱스를 result에 할당한다. 실행 x
2번째 반복 : 만약 arr의 2번째 인덱스(3)와 arr의 1번째 인덱스(1)가 같지 않다면 arr의 1번째 인덱스(1)를 result에 할당한다. 실행 o
3번째 반복 : 만약 arr의 3번째 인덱스(3)와 arr의 2번째 인덱스(3)가 같지 않다면 arr의 2번째 인덱스(3)를 result에 할당한다. 실행 x
4번째 반복 : 만약 arr의 4번째 인덱스(0)와 arr의 3번째 인덱스(3)가 같지 않다면 arr의 3번째 인덱스(3)를 result에 할당한다. 실행 o
5번째 반복 : 만약 arr의 5번째 인덱스(1)와 arr의 4번째 인덱스(0)가 같지 않다면 arr의 4번째 인덱스(0)를 result에 할당한다. 실행 o
6번째 반복 : 만약 arr의 6번째 인덱스(1)와 arr의 5번째 인덱스(1)가 같지 않다면 arr의 5번째 인덱스(1)를 result에 할당한다. 실행 x
7번째 반복 : 만약 arr의 7번째 인덱스(undefined)와 arr의 6번째 인덱스(1)가 같지 않다면 arr의 6번째 인덱스(1)를 result에 할당한다. 실행 o
위와 같은 내용으로 반복문이 종료된다. 이때 result에 할당된 값은 [1,3,0,1]이다. 이때 존재하지 않는 인덱스 값을 지정했을때 undefined가 나온다는 점을 알아두면 좋겠다.
# 다른 사람의 풀이
function solution(arr)
{
return arr.filter((val,index) => val != arr[index+1]);
}
filter() 메소드는 배열의 각 요소를 특정 조건에 따라 필터링하여 새로운 배열을 반환하는 메소드이다. 이때 콜백 함수의 반환 값이 'true'인 요소들만 필터링하여 새로운 배열을 리턴한다.
위 코드에서는 val(현재요소)과 index를 사용하여 val(현재요소)와 arr[index+1] 즉, 다음번째 요소가 같은지 비교해서 같지 않다면 필터링해서 리턴하는 과정을 거치고 있다.
function solution(numbers) {
let array = []
for(i=0; i < numbers.length; i++){
for(j= i+1; j < numbers.length; j++){
array.push(numbers[i]+numbers[j])
}
}
let set = [...new Set(array)]
return set.sort((a,b)=> a-b)
}
이중 반복문을 사용해 모든 가능한 숫자 조합의 합을 배열에 추가하기 위해 순차적으로 numbers의 0번째 인덱스와 1번째 인덱스 값을 더하고 0번째 인덱스와 2번째 인덱스 값을 더하고 ... 4번째 인덱스와 4번째 인덱스값 까지 더한 값을 array에 넣었다.
배열에서 중복된 값을 제거하기 위해 Set 객체를 사용한다. Set은 중복된 값을 허용하지 않는 자료형으로, 중복을 제거한 값을 다시 배열로 변환하여 set 변수에 저장한다.
이때 만약 let set = new set(array) 와 같이 코드를 구성하고 set 을 console 찍어보면 Set(6) { 3, 5, 6, 4, 2, 7 } 와 같이 출력된다.
따라서 Array.from() 메소드를 사용하거나 위 코드와 같이 배열로 감싼 후 스프레드 연산자를 사용해 배열화 시켜야 한다.
function solution(lottos, win_nums) {
let bestCount = 0
let worthCount = 0
let bestRank = 0
let worstRank = 0
for (i = 0; i < lottos.length; i++) {
if (win_nums.includes(lottos[i])) {
bestCount++
}
if (lottos[i] === 0) {
bestCount++
}
}
for (i = 0; i < lottos.length; i++) {
if (win_nums.includes(lottos[i])) {
worthCount++
}
}
if(bestCount === 6){
bestRank = 1
}else if(bestCount === 5){
bestRank = 2
}else if(bestCount === 4){
bestRank = 3
}else if(bestCount === 3){
bestRank = 4
}else if(bestCount === 2){
bestRank = 5
}else{
bestRank = 6
}
if(worthCount === 6){
worstRank = 1
}else if(worthCount === 5){
worstRank = 2
}else if(worthCount === 4){
worstRank = 3
}else if(worthCount === 3){
worstRank = 4
}else if(worthCount === 2){
worstRank = 5
}else{
worstRank = 6
}
return [bestRank, worstRank]
}
console.log(solution([44, 1, 0, 0, 31, 25], [31, 10, 45, 1, 6, 19]))
console.log(solution([0, 0, 0, 0, 0, 0], [38, 19, 20, 40, 15, 25]))
console.log(solution([45, 4, 35, 20, 3, 9], [20, 9, 3, 45, 4, 35]))
console.log(solution([97, 96, 99, 98, 95, 94],[31, 10, 45, 1, 6, 19]))
뽑힐 수 있는 가장 높은 등수와 가장 낮은 등수를 배열에 담아 리턴해야 한다.
실제로 숫자를 맞췄을때와 lottos 요소에 0이 있을때마다 bestCount을 1씩 올려줬다. 만약 bestCount가 6이라면(6개를 맞췄다면) bestRank(등수를 표현)을 1이 되는 방식이다.
worthCount는 lottos 요소 중 0이 있을땐 카운트를 올리지 않고 숫자가 일치할때만 카운트가 올라가게 했다.
마찬가지로 worthCount에 해당하는 값이 있을때 worstRank에 등수를 할당하여 리턴하게 했다.
# 다른 사람의 코드
function solution(lottos, win_nums) {
const rank = [6, 6, 5, 4, 3, 2, 1];
let minCount = lottos.filter(v => win_nums.includes(v)).length;
let zeroCount = lottos.filter(v => !v).length;
const maxCount = minCount + zeroCount;
return [rank[maxCount], rank[minCount]];
}
lottos.filter(v => win_nums.includes(v)) 를 console.log 찍어보면 lottos와 win_nums 배열 사이의 같은 값을 리턴하고 length 를 사용해 같은 값이 몇개 있는지를 minCount에 할당한다.
이때 includes() 메소드는 배열이 특정 요소를 포함하고 있는지를 확인하는 메소드인데, lottos의 요소가 하나씩 v에 들어오면서 win_nums의 배열 요소를 includes() 메소드를 사용해 있는지 없는지 여부를 판단해 만약 있다면 true가 리턴되고 true가 리턴된 v 값은 filter 메소드를 통해 걸러져서 리턴되게 된다.
lottos.filter(v => !v)는 0이 false임을 이용한 코드인데, lottos의 요소들이 하나씩 v에 들어오면서 만약 0이 들어오게 된다면 !v에 의해 true가 되므로 0 리턴되고 length를 사용해 0이 리턴된 횟수 즉, lottos 내에 존재하는 0의 개수를 zeroCount에 할당하게 된다.
maxCount, 당첨될 수 있는 최대 등수는 0이 정답이라고 가정해야하므로 minCount 에 zeroCount를 더해줘서 할당한다.
마지막으로 maxCount가 6이라면 rank의 6번째 인덱스, 1등이 출력될 수 있게하고 minCount가 0이라면 rank의 0번째 인덱스, 6등이 출력될 수 있게 한다. 0개 혹은 1개를 맞췄을때는 6등이므로 rank의 0번째, 1번째 인덱스를 6으로 설정해줬다.
function solution(answers) {
let answer = [];
const man1 = [1, 2, 3, 4, 5];
const man2 = [2, 1, 2, 3, 2, 4, 2, 5];
const man3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5];
let score = [0, 0, 0];
for (let i = 0; i < answers.length; i++) {
if (answers[i] === man1[i % man1.length]) score[0]++;
if (answers[i] === man2[i % man2.length]) score[1]++;
if (answers[i] === man3[i % man3.length]) score[2]++;
}
const max = Math.max(...score);
for (let i = 0; i < score.length; i++) {
if (max === score[i]) {
answer.push(i + 1);
}
}
return answer;
}
수포자 1,2,3이 찍는 패턴을 각 변수에 배열 형태로 할당해줬다. answers의 0번째 인덱스와 man1의 0 % man1.length(=0)번째 인덱스가 같다면 score의 0번째 인덱스가 1씩 올라가게 했다. 이때 % 연산자를 사용해서 수포자들이 찍는 패턴이 반복되게 했다.
수포자들의 점수가 담긴 score 배열에서 Math.max() 함수를 사용하여 가장 높은 값을 max에 할당한다.
만약 max와 score의 i번째 인덱스 요소가 같다면 i + 1 한 값을 answer에 push 하는데, 이는 가장 높은 점수를 가진 수포자의 번호를 answer에 추가하기 위함이다.