2024. 2. 7. 22:45ㆍ알고리즘
백준 10816
문제
숫자 카드는 정수 하나가 적혀져 있는 카드이다. 상근이는 숫자 카드 N개를 가지고 있다. 정수 M개가 주어졌을 때, 이 수가 적혀있는 숫자 카드를 상근이가 몇 개 가지고 있는지 구하는 프로그램을 작성하시오.
입력
첫째 줄에 상근이가 가지고 있는 숫자 카드의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 숫자 카드에 적혀있는 정수가 주어진다. 숫자 카드에 적혀있는 수는 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다.
셋째 줄에는 M(1 ≤ M ≤ 500,000)이 주어진다. 넷째 줄에는 상근이가 몇 개 가지고 있는 숫자 카드인지 구해야 할 M개의 정수가 주어지며, 이 수는 공백으로 구분되어져 있다. 이 수도 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다.
출력
첫째 줄에 입력으로 주어진 M개의 수에 대해서, 각 수가 적힌 숫자 카드를 상근이가 몇 개 가지고 있는지를 공백으로 구분해 출력한다.
예제 입력 1
10
6 3 2 10 10 10 -10 -10 7 3
8
10 9 -5 2 3 4 5 -10
예제 출력 1
3 0 0 1 2 0 0 2
📝문제풀이
직관적이고 단순한 문제이다. 카드를 순회하며 일치 갯수를 세어주면 된다.
function count(arr, num) {
let result = 0;
let lt = 0;
let rt = arr.length - 1;
while (lt <= rt) {
const mid = parseInt((lt + rt) / 2);
if (arr[mid] === num) {
result++;
let leftT = mid - 1;
let rightT = mid + 1;
while (arr[leftT] === num) {
result++;
leftT -= 1;
}
while (arr[rightT] === num) {
result++;
rightT += 1;
}
return result;
} else if (arr[mid] > num) rt = mid - 1;
else lt = mid + 1;
}
return 0;
}
function solution(arr1, arr2) {
const result = [];
arr1.sort((a, b) => a - b);
arr2.forEach((num) => {
result.push(count(arr1, num));
});
return result.join(' ');
}
하지만 시간 초과가 계속 나왔다. 시간복잡도를 계산하면 최악의 경우 O(n^3*logn)이 나올 수 있다.
반복문 안에 반복문을 사용한 이유는 중복된 요소가 있을 수 있기 때문이다.
하지만 시간 초과를 해결하기 위해선 반복문 내부에 반복문이 존재해서는 안된다.
이를 해결하기위해 해쉬맵을 활용하기로 했다.
카드의 각 요소의 갯수를 해쉬맵에 저장하고, 이진탐색을 하면서 카드가 존재하면 요소의 갯수를 해쉬맵에서 찾아 구해주면 된다. 이 경우에는 시간복잡도 O(nlogn)을 갖는다.
function isInclude(arr, target) {
let lt = 0;
let rt = arr.length - 1;
while (lt <= rt) {
const mid = parseInt((lt + rt) / 2);
if (arr[mid] > target) rt = mid - 1;
else if (arr[mid] < target) lt = mid + 1;
else return true;
}
return false;
}
function solution(arr1, arr2) {
let result = '';
const hashMap = new Map();
arr1.sort((a, b) => a - b);
arr1.forEach((num) => {
if (hashMap.has(num)) hashMap.set(num, hashMap.get(num) + 1);
else hashMap.set(num, 1);
});
arr2.forEach((num) => {
if (isInclude(arr1, num)) result += hashMap.get(num).toString() + ' ';
else result += '0' + ' ';
});
return result;
}
느낀점
이 문제를 정리한 이유는 기능의 분리에 대해 다시 한 번 생각해보자는 취지다.
이분탐색을 하면서 중복된 요소의 갯수를 새려고 하니 테스트에 통과하지 못했다.
중복된 요소의 갯수는 해쉬맵을 사용하여 기능을 분리한다면 쉽게 해결할 수 있었다.
구현하려는 기능에 반복문을 수행하면서 복잡한 반복문을 또 사용한다면 기능을 분리해보는 생각을 가져보아야겠다.
'알고리즘' 카테고리의 다른 글
결정 알고리즘(이진탐색) - K번째 수 (2) | 2024.02.08 |
---|---|
결정 알고리즘(이분탐색) - 공유기 설치 (1) | 2024.02.08 |
결정 알고리즘(이분검색) - 뮤직비디오 (1) | 2024.02.07 |
그리디 - 결혼식, 강의실 배정 (0) | 2024.02.07 |
그리디 - 설탕배달 (1) | 2024.02.06 |