알고리즘 스터디 1일차 - 문제 풀이(Javascript)

싱클베어·2022년 1월 14일
0

algorithm

목록 보기
1/6
post-custom-banner

아래 4개의 문제에 대해 문제 풀이를 작성하였습니다.

프로그래머스 - 연습문제 - 직사각형 별찍기
프로그래머스 - 연습문제 - 두 정수 사이의 합
프로그래머스 - 월간 코드 챌린지 시즌2 - 음양 더하기
프로그래머스 - 연습문제 - 행렬의 덧셈

1. 직사각형 별찍기 (q1)


문제 설명

이 문제에는 표준 입력으로 두 개의 정수 n과 m이 주어집니다.
별(*) 문자를 이용해 가로의 길이가 n, 세로의 길이가 m인 직사각형 형태를 출력해보세요.

제한 조건

n과 m은 각각 1000 이하인 자연수입니다.

예시

입력
5, 3

출력

*****
*****
*****

나의 풀이

process.stdin.setEncoding('utf8');
process.stdin.on('data', data => {
    const n = data.split(" ");
    const a = Number(n[0]), b = Number(n[1]);
    var width = ''
    var result = ''
    for (let j = 0; j < b; j++) {
        for (let i = 0; i < a; i++) {
            width += '*';        
        }
        width += '\n'
        result += width;
        width=''
    }
    console.log(result);
});

직사각형에 대해 첫번째 입력값 a를 가로, 두번째 입력값을 b를 세로로 두고 이중 for문을 수행한다.
세로로 한 줄씩 가로 a값의 크기만큼 * 문자를 추가하여 width 변수에 저장한 후, 한 줄이 모두 끝났을때 개행문자 \n 을 추가하고 다음 줄로 이동하여 result 값에 저장한다.

다른사람의 풀이

process.stdin.setEncoding('utf8');
process.stdin.on('data', data => {
    const n = data.split(" ");
    const a = Number(n[0]), b = Number(n[1]);
    const star = `${'*'.repeat(a)}\n`;

    console.log(star.repeat(b));
});

다른 사람의 풀이를 살펴보며 repeat 라는 함수를 확인할 수 있었고, 사용 예는 아래와 같다.

  • string.repeat(n) - string문자열을 n번 반복합니다.

2. 두 정수 사이의 합 (q4)


문제 설명

두 정수 a, b가 주어졌을 때 a와 b 사이에 속한 모든 정수의 합을 리턴하는 함수, solution을 완성하세요.
예를 들어 a = 3, b = 5인 경우, 3 + 4 + 5 = 12이므로 12를 리턴합니다.

제한 조건

  • a와 b가 같은 경우는 둘 중 아무 수나 리턴하세요.
  • a와 b는 -10,000,000 이상 10,000,000 이하인 정수입니다.
  • a와 b의 대소관계는 정해져있지 않습니다.

예시

입력
a=3, b=5
a=3, b=3
a=5, b=3

출력
return=12
return=3
return=12


나의 풀이

function solution(a, b) {
    var answer = 0;
    // a가 b보다 큰 경우
    if (a > b){
        for (let j = b; j <= a; j++){
            answer += j
        }
    } else if (b > a) { // b가 a보다 큰 경우
        for (let i = a; i <= b; i++){
            answer += i
        }
    } else { // a === b 인 경우
        answer = a
    }
    return answer;
}

ab의 대소 관계가 정해지지 않았으므로, 경우의 수는 3가지

  • a > b, b > a, a === b

세 가지 케이스에 대해 if~else문을 작성하고, for문을 돌며 answer 변수에 ab 사이의 값을 모두 더한다.
이 때, 두 가지 숫자 중 더 큰 값을 포함해야 하므로 a > bfor문에서
for (let j = b; j < a; j++) 가 아닌,
for (let j = b; j <= a; j++)a 값을 포함하여 계산한다.

다만 이 방식으로 문제를 풀 경우, 정수 입력값이 -10,000,000 에서 10,000,000 사이 이기 때문에, 예제의 최대 입력값과 최소 입력값이 입력될 경우 시간이 오래 걸리는 것을 확인하였다(프로그래머스 채점 기준 소요시간 0.04ms ~ 28.23ms까지 다양했음).

다른 방법이 필요해 추가로 검색을 진행했다.

다른 사람의 풀이

function solution(a, b){
    return (a+b)*(Math.abs(b-a)+1)/2;
}

1부터 100까지의 합을 공식화 했을때 100 * (100+1)/2 = 5050 형태인것을 응용하여, 아주 깔끔하게 풀어낸 예시였다. 그리고 이 예시는 사실 아래와 같이 풀어 쓸 수 있다.

등차수열의 제1항 a, 마지막n항 b, a와 b사이의 정수 개수 n.

answer = (a+b) * n / 2

n 을 구하기 위해선, 주어진 두 정수 중에서 큰 수에서 작은 수를 뺀 후 +1을 하면 나온다. ab 의 크기 비교를 진행하고 a가 클 경우 a-b 를, b 가 클 경우 b-a를 수행하려고 하였으나 위 풀이에서는 아래 함수를 사용해 해결하였다.

Math.abs(number) 는 주어진 숫자 number 의 절대값을 반환한다.

따라서, ab의 대소 비교를 할 필요 없이 한쪽에서 값을 뺀 후 절대값을 취해준 뒤, +1을 하면 갯수가 정확하게 나온다.


3. 음양 더하기 (q7)


문제 설명

어떤 정수들이 있습니다. 이 정수들의 절댓값을 차례대로 담은 정수 배열 absolutes와 이 정수들의 부호를 차례대로 담은 불리언 배열 signs가 매개변수로 주어집니다. 실제 정수들의 합을 구하여 return 하도록 solution 함수를 완성해주세요.

제한 조건

absolutes의 길이는 1 이상 1,000 이하입니다.

  • absolutes의 모든 수는 각각 1 이상 1,000 이하입니다.

signs의 길이는 absolutes의 길이와 같습니다.

  • signs[i] 가 참이면 absolutes[i] 의 실제 정수가 양수임을, 그렇지 않으면 음수임을 의미합니다.

예시

입력

  • absolutes : [4,7,12]
    signs : [true, false, true]
  • absolutes : [1,2,3]
    signs : [false, false, true]

출력

  • result : 9
    -> (+4 -7 +12)
  • result : 0
    -> (-1 -2 +3)

나의 풀이

function solution(absolutes, signs) {
    var answer = 0;
    for (let i = 0; i < signs.length; i++){
        if (signs[i] === true){
            answer += absolutes[i];
        } else {
            answer += absolutes[i]*-1;
        }    
    }
    return answer;
}

absolutes 배열과 signs 배열의 크기는 같다고 주어졌기 때문에, for 문을 돌며 signs 배열 내의 값을 가져와 true 일 경우엔 양의 정수 그대로 answer에 더하고, false인 경우는 absolutes[i] 값에 -1을 곱하여 answer에 더해 결과값을 도출하였다.

다른사람의 풀이

function solution(absolutes, signs) {
    let answer = 0;
    for (let i = 0; i < signs.length; i++) {
        signs[i] ? answer += absolutes[i] : answer -= absolutes[i]
    }
    return answer;
}

삼항 연산자를 사용하고, signs[i] 값이 false인 경우 -1을 곱해서 더하지 않고 그냥 빼게끔 구현되었다. MDN Web Docs 에 제시된 예시가 이해가 빨랐다.

function getFee(isMember) {
  return (isMember ? '$2.00' : '$10.00');
}

isMember 함수를 통해, isMembertrue인 경우 '$2.00' 를 리턴값으로 주고 false, null 인 경우 '$10.00' 을 리턴값으로 반환한다.


4. 행렬의 덧셈 (q10)


문제 설명

행렬의 덧셈은 행과 열의 크기가 같은 두 행렬의 같은 행, 같은 열의 값을 서로 더한 결과가 됩니다. 2개의 행렬 arr1과 arr2를 입력받아, 행렬 덧셈의 결과를 반환하는 함수, solution을 완성해주세요.

제한 조건

  • 행렬 arr1, arr2의 행과 열의 길이는 500을 넘지 않습니다.

예시

입력

  • arr1 : [[1,2],[2,3]], arr2 : [[3,4],[5,6]]
  • arr1 : [[1],[2]], arr2 : [[3],[4]]

출력

  • result : [[4,6],[7,9]]
  • result : [[4],[6]]

나의 풀이

function solution(arr1, arr2) {
    
    // 리턴 값을 배열 리터럴 []; 로 미리 생성. Array() 생성자 함수로 선언한 것과 동일
    var answer = [];
    
    // 행렬 덧셈 시작
    for (var i=0; i<arr1.length; i++) {
      	answer[i] = []; // 생성한 배열 안에 배열을 추가하여 중첩 배열 생성
      	for (var j=0; j<arr1[i].length; j++) {
            answer[i][j] = arr1[i][j] + arr2[i][j];
        }
    }
    return answer;
}

자바스크립트에서의 배열은 다른 언어와 다른 점 2가지를 들었다.

  • 배열 내부의 데이터 타입은 서로 다를 수 있다.
  • 배열의 크기는 동적으로 변경될 수 있다.

따라서 배열 내부에 배열을 담을 수 있다. 배열 안의 배열 요소에 대한 접근은 array[0][1]; 과 같이 접근할 수 있는데, 아래 console.table(array); 함수를 사용하면 시각적으로 볼 수 있어서 배열 요소를 탐색하는데 도움이 많이 되었다.

var array = solution([[1, 2], [2, 3]], [[3, 4], [5, 6]]);
console.table(array);
console.log(array([0][1])); // 1행 2열의 = 6 반환
(index)01
046
179

다른사람의 풀이

function solution(A, B){
    let answer_array = new Array();
  	answer_array = A.map((a, i) => a.map((b, j) => b + B[i][j]));
  	return answer_array;
}

// 아래는 테스트로 출력해 보기 위한 코드입니다.
console.log(solution([[1,2], [2,3]], [[3,4],[5,6]])) 

Array.map , => 등의 못보던 함수를 사용하여 구현됐다.
Array.map은 주어진 3개의 인자 (currentValue, index => function)를 사용해 .map을 호출한 배열의 내부 값을 순차적으로 탐색하며 function을 수행한 뒤, 새로운 배열을 만들어서 리턴한다고 한다. 아래 예제로 확인해보면,


const numbers = [2, 3, 4];
numbers.map((number, index) => { 
  // number: 현재 처리중인 배열의 element(요소값)
  // index: 현재 처리중인 source배열의 index 
  console.log(number, index); // 2, 0
  return number * number; 
});
    
  // return : [4, 9, 16]

위 코드는 아래와 같이 풀어 쓸수 있다.

const numbers = [2, 3, 4];
function Mathpow(number){
  return number * number; // Math.pow(number,2);
}
let newNumbers = numbers.map((number, index)=> Mathpow(number));
// index를 생략할경우 : let newNumbers = numbers.map(number => Mathpow(number));
console.log(newNumbers)

log를 찍어보면 처음 표시되는 것은 배열의 index[0]번째 요소값 2, 현재의 index 값과 현재 처리중인 배열인 numbers 배열이다.
위 예제에서 console.log(number, index); 만 실행시켰다면 배열을 순차적으로 탐색하며 요소값과 index값이 나오게 된다. 2 0 / 3 1 / 4 2 순으로 콘솔에 찍히게 된다.

다른사람의 풀이를 하나씩 분리해보면 아래와 같다.

A 배열 [[1,2],[2,3]]

Array A01
0[1,2][2,3]

B 배열 [[3,4],[5,6]]

Array B01
0[3,4][5,6]
A.map((a, i) => ... // a=Array[1,2], i=0

중첩배열 Array A 의 첫번째 요소(A[i]) a=[1,2] 에 처음 도달한다.

Array "A"01
0[1,2][2,3]
A.map((a, i) => a.map((b, j) => // b=1, j=0

배열 Array A[i] 의 첫번째 요소(A[i][j]) b=1을 찾는다.

Array "A[0]"01
012
A.map((a, i) => a.map((b, j) => b + B[i][j])) // b + B[0][0]

위에서 찾아둔 b와 Array B[i][j], 즉 B[0][0] = 3 값을 b 와 더한다.

Array "B"01
0[3,4][5,6]
answer_array = A.map((a, i) => a.map((b, j) => b + B[i][j]));

Array answer_array[0][0]값에 b + B[0][0] 값을 더해서 넣는다. 이후 다른 행렬에도 반복 작업 수행.

Array "answer_array"01
04

결과

Array "answer_array"01
046
179

참고 URL

  1. 직사각형 별찍기
    자료구조와 자료형 - 문자열

  2. 두 정수 사이의 합
    1부터 n까지의 합 구하기 - 알고리즘 계산 복잡도
    등차수열의 합, 등차수열의 합 공식

  3. 음양 더하기
    MDN Web Docs - 삼항 조건 연산자

  4. 행렬의 덧셈

    자바스크립트 배열(Array) 생성 및 사용법 쉽게 정리
    자바스크립트 2차원 배열 선언 및 사용법
    2차원 배열과 다차원 배열 그리고 중첩 배열
    Javascript - Array map 사용법
    var, let, const의 차이
    배열 map() 함수로 변경된 새로운 배열 생성하기

profile
안녕하세요.
post-custom-banner

0개의 댓글