Jaeilit

백준 1300 K번째 수 Js 본문

알고리즘

백준 1300 K번째 수 Js

Jaeilit 2022. 10. 6. 11:49
728x90

https://www.acmicpc.net/problem/1300

 

1300번: K번째 수

세준이는 크기가 N×N인 배열 A를 만들었다. 배열에 들어있는 수 A[i][j] = i×j 이다. 이 수를 일차원 배열 B에 넣으면 B의 크기는 N×N이 된다. B를 오름차순 정렬했을 때, B[k]를 구해보자. 배열 A와 B

www.acmicpc.net

 

틀린 내 코드

 

const fs = require("fs");

const filePath =
  process.platform === "linux" ? "/dev/stdin" : "./이분탐색/1300/input.txt";

const [N, K] = fs.readFileSync(filePath).toString().trim().split("\n");

const ary = Array.from({ length: N }, (v, i) => {
  let result = [];
  let n = 1;
  let index = i + 1;

  for (let k = 0; k < N; k++) {
    result.push(n * index);
    n++;
  }

  return result;
});

let sort = [];

for (let i = 0; i < ary.length; i++) {
  for (let j = 0; j < ary.length; j++) {
    sort.push(ary[i][j]);
  }
}

sort.sort((a, b) => a - b);

function binary(ary, target) {
  let start = 0;
  let end = ary.length - 1;
  let answer = 0;

  let mid = Math.floor((start + end) / 2);
  while (ary[mid] !== target && start <= end) {
    if (target >= mid) {
      answer = ary[mid];
      start = mid + 1;
    } else {
      end = mid - 1;
    }

    mid = Math.floor((start + end) / 2);
  }

  return answer;
}

console.log(binary(sort, K)); //6
console.log(sort, ary);
// ansewr 6
// sort [(1, 2, 2, 3, 3, 4, 6, 6, 9)]
// ary [([1, 2, 3], [2, 4, 6], [3, 6, 9])];

// A = [
//   [1, 2, 3],
//   [2, 4, 6],
//   [3, 6, 9],
// ];
// B = [1, 2, 2, 3, 3, 4, 6, 6, 9];

// 메모리초과;

 

로직

 

문제 그대로 배열을 만들어주고 오름차순 정렬을 한 뒤에 K 번째 수를 이분탐색으로 찾았다.

채점결과는 메모리초과인데 최대 입력이 10만인데 10만X10만 배열을 만드는 순간 메모리초과가 된다.

 

그럼 배열을 만들지 않고 풀어야하는 문제인데

어떻게 풀 수 있을까

 

정답코드

const fs = require("fs");

const filePath =
  process.platform === "linux" ? "/dev/stdin" : "./이분탐색/1300/input.txt";

let input = fs.readFileSync(filePath).toString().trim().split("\n").map(Number);

const [N, k] = input;

let left = 1;
let right = k;
let answer = 0;

function countOrder(mid) {
  let cnt = 0;

  for (let i = 1; i <= N; i++) {
    cnt += Math.min(parseInt(mid / i), N);
  }

  return cnt;
}

while (left <= right) {
  let mid = parseInt((left + right) / 2);
  let count = countOrder(mid);

  if (count >= k) {
    answer = mid;
    right = mid - 1;
  } else {
    left = mid + 1;
  }
}

console.log(answer);

// N = 3 K = 6
// [1, 2, 3, 4, 5, 6]

// [
  1, 2, 2, 3, 3,
  4, 6, 6, 9
] 
// [ [ 1, 2, 3 ], [ 2, 4, 6 ], [ 3, 6, 9 ] ]

// 1 3 6 left, mid, right
// 3 mid
// 1 3 3 3 for i, parseInt, N, count
// 2 1 3 4 for i, parseInt, N, count
// 3 1 3 5 for i, parseInt, N, count
// 5 cnt

// 4 5 6 left, mid, right
// 5 mid
// 1 5 3 3 for i, parseInt, N, count
// 2 2 3 5 for i, parseInt, N, count
// 3 1 3 6 for i, parseInt, N, count
// 6 cnt

// 4 4 4 left, mid, right
// 4 mid
// 1 4 3 3 for i, parseInt, N, count
// 2 2 3 5 for i, parseInt, N, count
// 3 1 3 6 for i, parseInt, N, count
// 6 cnt

// 4 mid === answer

로직설명

  • 입력과 배열 주석은 이해를 돕기 위해 작성한것입니다.
  • 1, 3,6 left mid, right 부터, k가 6이니까 문제에서 인덱스는 1번이라는 힌트로 1~6까지 숫자가 있는 배열을 만듭니다.
    • 이 정도 배열은 입력이 10만이라도 메모리초과가 되지않습니다.
  • 여기서 mid 값은 3인데 mid 라해서 mid 라고 생각하지말고 기준 값이라고 생각을 해서 count 함수 로직으로 보냅니다.
    • count 함수에서는 for문으로 N만큼 도는데 이유는 N*N 의 배열을 만든다고 했기 때문에 가로로 N 만큼 표현한겁니다.
    • For의 인덱스(i) 에서 mid 기준 값 3을 나눈 값은 3보다 작은 값이 몇개냐라는 의미가 됩니다.
    • 예시로 첫번째 지문에 i = 1 나누기 값(작은 값) =  3(mid/i) n = 3 은 미드 3보다 작은 값이 3개라는 건데 이건 N*N 에서 첫번째 배열 N[0] 번째인 [1, 2, 3] 입니다
    • 두번째 i = 2 계산 값 (mid/i) = 1 n = 3 은 [2, 4, 6] 배열에서 3보다 작은 값이 몇개냐 입니다. 1개죠? 카운터에 누산해줍니다. 카운터 = 4
    • 세번째 i =3 계산 값 (mid/i) = 1 n = 3 은 [3, 6, 9] 배열에서 3보다 작은 값은 중복 값이 있을 수 있으니 3도 포함해줍니다 1개입니다. 카운터는 = 5
    •  K가 6 일때 첫번째 카운터 값은 5입니다. 하지만 우리가 찾는것은 k 가 배열의 몇번째 숫자인지 입니다. 다르게 이야기하면 k 보다 작은 값이 몇개가 있냐 => 카운터 값 >= k 가 됩니다.
    • 일단 카운터는 5였고 k 는 6이니까 더 큰 값에 가서 k 를 찾아야합니다. start 또는 left 를 mid +1 로 옮겨줍니다.
    • 이런식으로 추려나가다보면 k 보다 작은 값 = 카운터번째 순번이 추려집니다. 답은 4

 

저는 지문 그대로 배열을 만들고 거기서 몇번째인지 찾으려고 단순하게 생각해서 메모리초과라는 벽을 만나고...

이게 왜 이분탐색이지라는 생각도하면서 ... 여튼간에 어려웠습니다.

 

좀 더 다른시점으로도 바라보고 접근하면서 논리적인 사고를 길러야할 것 같네요..

728x90

'알고리즘' 카테고리의 다른 글

백준 좌표압축 18870 js  (0) 2022.10.17
백준 1181 단어 정렬 js  (0) 2022.10.13
백준 공유기 설치 2110 js  (1) 2022.10.04
백준 10815 숫자카드 js  (0) 2022.10.04
백준 1654 랜선자르기 js  (1) 2022.10.04