"나는 무엇을 풀었는가" 시리즈는 이렇게 시작했습니다.

  1. 취업 준비 중 몇 번의 코딩테스트를 보며 깨달은 것이 있습니다. 바로 "기초가 중요하다"는 것입니다. 그리하여 프로그래머스 Level.0부터 차근차근 다시 풀어보려고 합니다.
  2. 단지 문제를 푸는 것보단, 왜 해당 함수를 썼는지 더 재사용이나 가독성을 높일 방법은 없는지, 그리고 해당 함수가 없다면 어떻게 풀 수 있을지와 같이 다양한 방법과 생각을 통해 사고력을 높이려고 노력합니다.
  3. 그럼 레츠 고 !

💡 배운 내용


1. 중복 요소를 제거하는 2가지 방법

배열 내 중복을 제거하는 방법으로는 대표적으로 2가지가 있다.

예시 배열:
const arr = ['곰', '사자', '기린', '곰', '치타', '말', '기린', '사슴']

1️⃣ filter() & indexOf()

return arr.filter((v, i) => arr.indexOf(v) === i);
// [ '곰', '사자', '기린', '치타', '말', '사슴' ]

2️⃣ set()

  • 이때 set() 은 기존 순서를 보장하지 않기 때문에 사용에 주의해야 한다.
 const set = new Set(arr);
return set;

// Set { '곰', '사자', '기린', '치타', '말', '사슴' }

2. flat() : 중첩 배열 평탄화

MDN Says : flat() 메서드는 모든 하위 배열 요소를 지정한 깊이까지 재귀적으로 이어붙인 새로운 배열을 생성합니다.

  • 쉽게 말하면 인자로 전달된 depth 까지 배열을 풀어준다. 예를 들어 2차원 배열을 flat()를 통해 1차원 배열로 만들어주는 셈이다.
    → 때문에 flat()은 중첩 배열 평탄화 메서드라고 불리운다.
  • 이때 인자로 아무값도 전달하지 않는 다면 기본값은 1이 된다.
// 2차원 배열 → 1차원 배열
const arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]

// 3차원 배열 → 2차원 배열
const arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

// 3차원 배열 → 1차원 배열
const arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]

// n차원 배열 → 1차원 배열
const arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

✏️ 풀이


1. [프로그래머스] 무작위로 K개의 수 뽑기

문제설명 : arr에서 중복을 제외한 수를 k개 만큼 뽑아 만든 배열을 리턴하세요. 이때 완성된 배열의 길이가 k보다 작으면 나머지 값을 전부 -1로 채워 리턴하세요.

입/출력 :

console.log(solution([0, 1, 1, 2, 2, 3], 3)); // [0, 1, 2]

Solution1 : Array() & fill() 활용하기

function solution(arr, k) {
    // 1. k 개수만큼 -1로 채운 배열을 만든다.
    const result = Array(k).fill(-1);
    // 2. 중복되지 않은 원소들을 구한다.
    const onlyNum = arr.filter((v, i) => arr.indexOf(v) === i);
    // 3. result 배열의 0 ~ onlyNum.length 만큼을 2번에서 구한 배열의 값으로 바꾼다.
    result.splice(0, onlyNum.length, ...onlyNum);
    // 4. k전까지 slice한 값을 리턴한다. (length는 1부터 시작하므로)
    return result.slice(0, k);
}

Solution2 : set 활용하기

  • set은 배열 내 중복된 요소를 제거한 배열을 리턴한다.
function solution(arr, k) {
    // 1. 중복된 요소를 제거한 배열을 만든다.
    const set = new Set(arr);
    // 2. 만든 배열에서 k개수까지 자른 후,
    const result = [...set].slice(0, k);
    // 3. length가 k와 같을 때까지 -1을 추가한다.
    while (result.length !== k) {
        result.push(-1);
    }
    return result;
}

2. [프로그래머스] 배열 만들기 6

문제설명 : 배열 arr에 조건에 맞춘 새로운 배열 stk를 만들어 리턴하세요.
조건 :

  • i의 초기값을 0으로 설정하고, i < arr.length일 때 다음을 반복한다.
  • stk.length === 0 ? stk.push(arr[i])하고 i++;
  • stk.length > 0 && stk[stk.length - 1] === arr[i] ? stk.pop(); i++;
  • stk.length > 0 && stk[stkv.length - 1] !== arr[i] ? stk.push(arr[i]); i++;
  • 모든 과정을 거친 후에도 stk이 빈배열이라면 -1을 리턴한다.

입/출력 :

console.log(solution([0, 1, 1, 1, 0])); // [0, 1, 0]

Solution1

function solution(arr) {
    let stk = [];
    let i = 0;
    
    while(i < arr.length) {
        if (stk.length > 0 && stk[stk.length - 1] === arr[i]) {
            stk.pop(); i++;
        }
        else if (stk.length >= 0 || stk[stk.length - 1] !== arr[i]) {
            stk.push(arr[i]); i++;
        }     
    }

    return stk.length !== 0 ? stk : [-1];
}

3. [프로그래머스] 수열과 구간 쿼리 4

문제설명 : queries의 원소는 각각 query를 나타내며, [s, e, k] 꼴이다.
arr[i]에 대해 1) s ≤ i ≤ e이고 2) i가 k의 배수이면 arr[i]에 1을 더한다.
위 규칙을 적용한 arr 배열을 리턴하세요.

입/출력 :

console.log(
  solution(
    [0, 1, 2, 4, 3],
    [
      [0, 4, 1],
      [0, 3, 2],
      [0, 3, 3],
    ]
  )
); // 	[3, 2, 4, 6, 4]

Solution1

// 조건 1 확인
function checkI(s, e, i) {
  return s <= i && i <= e;
}

// 조건 2 확인
function checkMultiple(i, k) {
  return i % k === 0;
}

function solution(arr, queries) {
  arr.map((_, i) => {
    queries.map(([s, e, k]) => {
      if (checkI(s, e, i) && checkMultiple(i, k)) {
        arr[i] += 1;
      }
    });
  });
  return arr;
}

🔥 4. [프로그래머스] 그림 확대

문제설명 : 1x1 크기의 정사각형으로 이루어진 배열 picture가 주어질 때, 가로 세로로 k배 늘린 배열을 리턴하세요.

입/출력 :

console.log(
  solution(
    [
      ".xx...xx.",
      "x..x.x..x",
      "x...x...x",
      ".x.....x.",
      "..x...x..",
      "...x.x...",
      "....x....",
    ],
    2
  )
); 

/* ["..xxxx......xxxx..", "..xxxx......xxxx..", 
    "xx....xx..xx....xx", "xx....xx..xx....xx", 
    "xx......xx......xx", "xx......xx......xx", 
    "..xx..........xx..", "..xx..........xx..", 
    "....xx......xx....", "....xx......xx....", 
    "......xx..xx......", "......xx..xx......", 
    "........xx........", "........xx........"] */
  

Solution1 : map 활용하기

function solution(picture, k) {
  let expansionPic = [];

  // 1. picture의 각 문자열에 map을 돌려 반복한다.
  picture.map(x => {
    // 2. picture[i]의 각 자리수를 배열로 만든 후 돌면서(map), 각 값을 k만큼 반복한 후 문자열로 변환하여 변수에 담는다.
    const bucket = [...x].map(v => v.repeat(k)).join('');
    // 3. 2번에서 만든 배열을 k번만큼 반복해 리턴할 배열에 담는다.
    for (let i = 0; i < k; i++) {
      expansionPic.push(bucket);
    }
  })

    return expansionPic;
}

Solution2 : 관심사 분리하기 (각 문자 반복)

function repeat(x, k) {
    const bucket = [];
    for (let i = 0; i < k; i++) {
        bucket.push(x);
    }
    return bucket;
}

function solution(picture, k) {
    return picture.map(x => {
        const bucket = [...x].map(v => v.repeat(k)).join('');
        return repeat(bucket, k);
    }).flat();
}

Solution3 : 관심사 한번 더 분리하기

function repeat(x, k) {
    const bucket = [];
    for (let i = 0; i < k; i++) {
        bucket.push(x);
    }
    return bucket;
}

function f(x, k) {
    return [...x].map(v => repeat(v, k).join('')).join('');
}

function solution(picture, k) {
    return picture
        .map(x => f(x, k))
        .map(x => repeat(x, k))
        .flat();
}

5. [프로그래머스] 문자열 겹쳐쓰기

문제설명 : my_string을 인데스 s부터 overwrite_string.length까지를 문자열 overwrite_string로 바꾸어 리턴하세요.

입/출력 :

console.log(solution("He11oWor1d", "lloWorl", 2)); // "HelloWorld"

Solution1

function solution(my_string, overwrite_string, s) {
  const str = [...my_string];
  const e = overwrite_string.length;
  str.splice(s, e, overwrite_string);

  return str.join("");
}

6. [프로그래머스] 배열 만들기 2

문제설명 : l 이상 r 이하의 정수 중에서 숫자 0과 5로만 이루어진 모든 정수를 오름차순으로 정렬한 배열을 리턴하세요.

입/출력 :

console.log(solution(5, 555)); // [5, 50, 55, 500, 505, 550, 555]

Solution1

function solution(l, r) {
  let result = [];

  for (let i = l; i <= r; i++) {
    // 숫자로는 5나 0이 들어있는지 확인하기 어렵기 때문에 문자 타입으로 변환한다.
    const strI = String(i);
    // 조건 : strI을 배열로 만들어 각 요소들이 5또는 0으로만 이루어져 있는지 확인하여 맞다면 result에 추가한다.
    if ([...strI].every((x) => x === "5" || x === "0")) {
      result.push(i);
    }
  }

  return result.length > 0 ? result : [-1];
}

7. [프로그래머스] 정사각형으로 만들기

문제설명 : 2차원 배열 arr에 대해 행과 열의 수가 같아지도록 각 행과 열에 끝에 0을 추가한 이차원 배열을 리턴하세요.

입/출력 :

console.log(
  solution([
    [572, 22, 37],
    [287, 726, 384],
    [85, 137, 292],
    [487, 13, 876],
  ])
); 
/* 	[
	 [572, 22, 37, 0], 
     [287, 726, 384, 0], 
     [85, 137, 292, 0], 
     [487, 13, 876, 0]
   ] */

Solution1

function solution(arr) {
  let rows = arr.length;
  let columns = arr[0].length;

  // 행 > 열
  if (rows > columns) {
    // arr[i]에 대해
    for (let i = 0; i < rows; i++) {
      // 행-열의 차이만큼 반복
      for (let j = columns; j < rows; j++) {
        arr[i].push(0);
      }
    }
  }

  // 행 < 열
  if (rows < columns) {
    for (let i = rows; i < columns; i++) {
      arr.push(Array(columns).fill(0));
    }
  }

  return arr;
}

Solution2 : 관심사 분리하기

// 하는 일 묶기
  function addEl(s, e, f) {
    for (let k = s; k < e; k++) {
      f();
    }
  }

function solution(arr) {
  let rows = arr.length;
  let columns = arr[0].length;

  // 행 > 열
  if (rows > columns) {
    // arr[i]에 대해
    for (let i = 0; i < rows; i++) {
      // 행-열의 차이만큼 반복
      addEl(columns, rows, () => arr[i].push(0));
    }
  }

  // 행 < 열
  if (rows < columns) {
    addEl(rows, columns, () => arr.push(Array(columns).fill(0)));
  }

  return arr;
}
profile
한입 크기로 베어먹는 개발지식 🍰

1개의 댓글

comment-user-thumbnail
2023년 8월 17일

정보 감사합니다.

답글 달기