- 문제
- 좌표들로 이루어진 배열을 입력받아 가장 가까운 두 점의 거리를 리턴
- 두 점의 거리를 계산하는 식이 따로 주어짐
- 계산식 값에 100을 곱한 후, 반올림하여 정수값만 리턴
- 시도
- 가장 단순히 생각했을 때, 좌표 간의 거리를 계산하는 방법은 각 좌표간의 차이를 보면 된다
- 좌표간의 x값의 차이값과 y값의 차이값을 절대값으로 더하면 좌표끼리의 순위를 매길 수 있다
- x, y 값의 차이를 통한 순위를 매겨 가장 작은 값의 좌표 2개의 인덱스를 저장시키고
- 마지막에 나온 좌표의 인덱스로 거리계산함수에 넣어 계산값을 리턴시킨다
- 효율적인 코드는 아니였지만, advanced를 제외하고는 모두 풀어내었다
- 풀어내고 나니, 내가 작성한 코드와 좌표거리계산함수의 형태가 거의 같다;;;
- 작성하고 나서, 레퍼런스를 보고 알았다, 그냥 대입해서 계산했어도 되었을 듯;;;
- 레퍼런스 코드는 나중에 다시 보고 분석해야 할 것 같다
- 이해하고 풀어보는데 오랜 시간이 걸릴 것 같다...
- 수도코드
function calculateDistance(p1, p2) {
const yDiff = p2[0] - p1[0];
const xDiff = p2[1] - p1[1];
return Math.sqrt(Math.pow(yDiff, 2) + Math.pow(xDiff, 2));
}
const closestPairOfPoints = function (points) {
let closer = [0,0];
let cur = Number.MAX_SAFE_INTEGER;
for (let i = 0; i < points.length - 1; i++) {
for (let j = i + 1; j < points.length; j++) {
let minX = Math.abs(points[i][0] - points[j][0]);
let minY = Math.abs(points[i][1] - points[j][1]);
if (cur > (minX + minY)) {
cur = (minX + minY);
closer = [i, j];
}
}
}
const dist = calculateDistance(points[closer[0]],points[closer[1]],)*100;
return Math.round(dist);
};
- 레퍼런스
function calculateDistance(p1, p2) {
const yDiffSquared = Math.pow(p2[0] - p1[0], 2);
const xDiffSquared = Math.pow(p2[1] - p1[1], 2);
const dist = Math.sqrt(yDiffSquared + xDiffSquared);
return Math.round(dist * 100);
}
const merge = function (left, right, comparator = (item) => item) {
let merged = [];
let leftIdx = 0,
rightIdx = 0;
const size = left.length + right.length;
for (let i = 0; i < size; i++) {
if (leftIdx >= left.length) {
merged.push(right[rightIdx]);
rightIdx++;
} else if (
rightIdx >= right.length ||
comparator(left[leftIdx]) <= comparator(right[rightIdx])
) {
merged.push(left[leftIdx]);
leftIdx++;
} else {
merged.push(right[rightIdx]);
rightIdx++;
}
}
return merged;
};
const mergeSort = function (arr, comparator) {
const aux = (start, end) => {
if (start >= end) return [arr[start]];
const mid = Math.floor((start + end) / 2);
const left = aux(start, mid);
const right = aux(mid + 1, end);
return merge(left, right, comparator);
};
return aux(0, arr.length - 1);
};
const closestPairOfPoints = function (points) {
const bruteForce = (start, end, sorted) => {
let min = Number.MAX_SAFE_INTEGER;
for (let src = start; src <= end; src++) {
for (let dst = src + 1; dst <= end; dst++) {
const dist = calculateDistance(sorted[src], sorted[dst]);
min = Math.min(min, dist);
}
}
return min;
};
const closestCrossing = (mid, sorted, min) => {
const strip = [];
const midX = sorted[mid][1];
let lIdx = mid - 1;
let rIdx = mid + 1;
while (
rIdx < sorted.length &&
Math.abs(midX - sorted[rIdx][1]) * 100 < min
) {
rIdx++;
}
while (lIdx >= 0 && Math.abs(midX - sorted[lIdx][1]) * 100 < min) {
lIdx--;
}
for (let i = lIdx + 1; i < rIdx; i++) {
for (let j = i + 1; j < rIdx; j++) {
min = Math.min(min, calculateDistance(sorted[i], sorted[j]));
}
}
return min;
};
const closestFrom = (start, end, size, sorted) => {
if (size <= 3) {
return bruteForce(start, end, sorted);
}
const mid = Math.floor((start + end) / 2);
const minLeft = closestFrom(start, mid, mid - start + 1, sorted);
const minRight = closestFrom(mid + 1, end, end - mid, sorted);
let min = Math.min(minLeft, minRight);
return closestCrossing(mid, sorted, min);
};
const sorted = mergeSort(points.slice(0), (item) => item[1]);
return closestFrom(0, sorted.length - 1, sorted.length, sorted);
};