From 927f88ae3ee2fbe899d65916500a70c8aa351127 Mon Sep 17 00:00:00 2001 From: Kohei Asai Date: Sun, 15 Sep 2019 23:09:10 -0700 Subject: [PATCH] 34. Find First and Last Position of Element in Sorted Array --- ...LastPositionOfElementInSortedArray.test.ts | 15 +++++ ...stAndLastPositionOfElementInSortedArray.ts | 59 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 solutions/findFirstAndLastPositionOfElementInSortedArray.test.ts create mode 100644 solutions/findFirstAndLastPositionOfElementInSortedArray.ts diff --git a/solutions/findFirstAndLastPositionOfElementInSortedArray.test.ts b/solutions/findFirstAndLastPositionOfElementInSortedArray.test.ts new file mode 100644 index 0000000..0a38026 --- /dev/null +++ b/solutions/findFirstAndLastPositionOfElementInSortedArray.test.ts @@ -0,0 +1,15 @@ +import searchRange from "./findFirstAndLastPositionOfElementInSortedArray"; + +const TEST_CASES = new Map<[number[], number], [number, number]>([ + [[[5, 7, 7, 8, 8, 10], 8], [3, 4]], + [[[5, 7, 7, 8, 8, 10], 6], [-1, -1]], + [[[2, 2], 2], [0, 1]] +]); + +describe("34. Find First and Last Position of Element in Sorted Array", () => { + for (const [args, expected] of TEST_CASES) { + test(`when [${args[0].join(", ")}], ${args[1]}`, () => { + expect(searchRange(args[0], args[1])).toEqual(expected); + }); + } +}); diff --git a/solutions/findFirstAndLastPositionOfElementInSortedArray.ts b/solutions/findFirstAndLastPositionOfElementInSortedArray.ts new file mode 100644 index 0000000..712204b --- /dev/null +++ b/solutions/findFirstAndLastPositionOfElementInSortedArray.ts @@ -0,0 +1,59 @@ +// 34. Find First and Last Position of Element in Sorted Array +// https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/ +export default function searchRange( + nums: number[], + target: number +): [number, number] { + // binary search to find the first index + let from = 0; + let to = nums.length; + + // loop until the search range shrinks to be from + 2 === to + while (to - from >= 3) { + const middle = Math.floor((from + to) / 2); + + if (nums[middle] >= target) { + to = middle + 1; + } else { + from = middle; + } + } + + // nums[from] or nums[to - 1] may point the target value + // otherwise, there's no target value + let first: number; + + if (nums[from] === target) { + first = from; + } else if (nums[to - 1] === target) { + first = to - 1; + } else { + return [-1, -1]; + } + + // binary search to find the last index + from = first >= 0 ? first : 0; + to = nums.length; + + // do the same binary search for the last index + while (to - from >= 3) { + const middle = Math.floor((from + to) / 2); + + if (nums[middle] <= target) { + from = middle; + } else { + to = middle + 1; + } + } + + let last: number; + + // pick to-value first because the values both from and to point could be target + if (nums[to - 1] === target) { + last = to - 1; + } else if (nums[from] === target) { + last = from; + } + + return [first, last!]; +}