JS-algorithm/BOJ

[백준] 두 수의 합 (javascript)

yunieyunie 2023. 7. 10. 21:01

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

 

3273번: 두 수의 합

n개의 서로 다른 양의 정수 a1, a2, ..., an으로 이루어진 수열이 있다. ai의 값은 1보다 크거나 같고, 1000000보다 작거나 같은 자연수이다. 자연수 x가 주어졌을 때, ai + aj = x (1 ≤ i < j ≤ n)을 만족하는

www.acmicpc.net

 

 

🤔 해결방법

1. 가지고 있는 숫자의 중복을 제거한다.

2. 만들어야 할 숫자에서 뺀 값이 들어있고 같은 숫자를 두 번 사용하지 않는 경우에만 answer+1을 한다.

 

 

🔑 풀이

const input = require("fs")
    .readFileSync("/dev/stdin")
    .toString()
    .trim()
    .split("\n");

  const haveNumber = input[1].split(" ").map(Number); //가지고 있는 숫자
  const makeNumber = input[2]; //만들어야 할 숫자
  let answer = 0;

  const numberSet = new Set(haveNumber); // 중복된 숫자 제거를 위해 Set 사용

  for (let i = 0; i < haveNumber.length; i++) {
    let target = makeNumber - haveNumber[i]
    if (numberSet.has(target) && haveNumber[i] !== target) answer++;
  }

  console.log(answer / 2); //중복이 있으므로 2로 나눔

 

 

😭 삽질

이중 for문으로 모든 숫자들을 더해서 만들어야 할 숫자가 되는지 확인하는 방법은 비효율적이라 만들어야 할 숫자에서 뺀 값이 haveNumber에 있는지 includes로 확인하는 코드를 작성했다.

하지만 시간 초과가 났다.

 

const input = require("fs")
    .readFileSync("/dev/stdin")
    .toString()
    .trim()
    .split("\n");

  const haveNumber = input[1].split(" ").map(Number); //가지고 있는 숫자
  const makeNumber = input[2]; //만들어야 할 숫자
  let answer = 0;

  for (let i = 0; i < haveNumber.length; i++) {
    if (haveNumber.includes(makeNumber - haveNumber[i])) answer++;
  }

  console.log(answer / 2); //중복이 있으므로 2로 나눔

 

includes 메서드는 결국 배열의 모든 요소를 순회하면서 값을 찾기 때문에 입력 배열의 크기가 클 경우 성능 문제가 발생할 수 있기 때문임을 알았다.

그래서 set.has를 사용했으나 이번엔 틀렸다고 나왔다...😥

 

const input = require("fs")
    .readFileSync("/dev/stdin")
    .toString()
    .trim()
    .split("\n");

  const haveNumber = input[1].split(" ").map(Number); //가지고 있는 숫자
  const makeNumber = input[2]; //만들어야 할 숫자
  let answer = 0;

  const numberSet = new Set(haveNumber); // 중복된 숫자 제거를 위해 Set 사용

  for (let i = 0; i < haveNumber.length; i++) {
    if (numberSet.has(makeNumber - haveNumber[i])) answer++;
  }

  console.log(answer / 2); //중복이 있으므로 2로 나눔

검색을 해보다가 haveNumber[i] !== target 조건을 추가했더니 정답으로 나왔다.

같은 숫자를 두 번 사용하여 makeNumber를 만드는 경우를 제외해야 했다.

 

예를 들어, haveNumber 배열이 [1, 2, 3, 4, 5]이고 makeNumber가 6인 경우 haveNumber[2]은 3이고, target은 3이다. numberSet에 target인 3이 존재하지만 haveNumber[2]와 target이 같은 숫자인 3이므로 중복된 숫자를 사용하는 경우이므로 answer를 증가시키지 않아야 하는 것이다..!

 

const input = require("fs")
    .readFileSync("/dev/stdin")
    .toString()
    .trim()
    .split("\n");

  const haveNumber = input[1].split(" ").map(Number); //가지고 있는 숫자
  const makeNumber = input[2]; //만들어야 할 숫자
  let answer = 0;

  const numberSet = new Set(haveNumber); // 중복된 숫자 제거를 위해 Set 사용

  for (let i = 0; i < haveNumber.length; i++) {
    let target = makeNumber - haveNumber[i]
    if (numberSet.has(target) && haveNumber[i] !== target) answer++;
  }

  console.log(answer / 2); //중복이 있으므로 2로 나눔

어렵지 않게 풀 수 있을거라 생각했던 문제였는데 생각치 못한 부분이 있었다.😂

쉬운 문제도 여러 케이스를 생각해보며 꼼꼼히 체크하는 습관이 필요하겠다!