diff --git a/src/main/java/g0401_0500/s0492_construct_the_rectangle/Solution.java b/src/main/java/g0401_0500/s0492_construct_the_rectangle/Solution.java new file mode 100644 index 000000000..87c70a04b --- /dev/null +++ b/src/main/java/g0401_0500/s0492_construct_the_rectangle/Solution.java @@ -0,0 +1,21 @@ +package g0401_0500.s0492_construct_the_rectangle; + +// #Easy #Math + +public class Solution { + /* + Algorithm: + - start with an index i from the square root all the way to 1; + - if at any time, area % i == 0 (so i is a divisor of area), then it's the closest solution. + */ + public int[] constructRectangle(int area) { + int low = (int) Math.sqrt(area); + while (low > 0) { + if (area % low == 0) { + return new int[] {area / low, low}; + } + low--; + } + return new int[] {0, 0}; + } +} diff --git a/src/main/java/g0401_0500/s0492_construct_the_rectangle/readme.md b/src/main/java/g0401_0500/s0492_construct_the_rectangle/readme.md new file mode 100644 index 000000000..351724075 --- /dev/null +++ b/src/main/java/g0401_0500/s0492_construct_the_rectangle/readme.md @@ -0,0 +1,35 @@ +492\. Construct the Rectangle + +Easy + +A web developer needs to know how to design a web page's size. So, given a specific rectangular web page’s area, your job by now is to design a rectangular web page, whose length L and width W satisfy the following requirements: + +1. The area of the rectangular web page you designed must equal to the given target area. +2. The width `W` should not be larger than the length `L`, which means `L >= W`. +3. The difference between length `L` and width `W` should be as small as possible. + +Return _an array `[L, W]` where `L` and `W` are the length and width of the web page you designed in sequence._ + +**Example 1:** + +**Input:** area = 4 + +**Output:** [2,2] + +**Explanation:** The target area is 4, and all the possible ways to construct it are [1,4], [2,2], [4,1]. But according to requirement 2, [1,4] is illegal; according to requirement 3, [4,1] is not optimal compared to [2,2]. So the length L is 2, and the width W is 2. + +**Example 2:** + +**Input:** area = 37 + +**Output:** [37,1] + +**Example 3:** + +**Input:** area = 122122 + +**Output:** [427,286] + +**Constraints:** + +* 1 <= area <= 107 \ No newline at end of file diff --git a/src/main/java/g0401_0500/s0493_reverse_pairs/Solution.java b/src/main/java/g0401_0500/s0493_reverse_pairs/Solution.java new file mode 100644 index 000000000..9533c9821 --- /dev/null +++ b/src/main/java/g0401_0500/s0493_reverse_pairs/Solution.java @@ -0,0 +1,33 @@ +package g0401_0500.s0493_reverse_pairs; + +// #Hard #Array #Binary_Search #Ordered_Set #Divide_and_Conquer #Segment_Tree #Binary_Indexed_Tree +// #Merge_Sort + +import java.util.Arrays; + +public class Solution { + // reference: + // https://discuss.leetcode.com/topic/78933/very-short-and-clear-mergesort-bst-java-solutions + public int reversePairs(int[] nums) { + return mergeSort(nums, 0, nums.length - 1); + } + + private int mergeSort(int[] nums, int start, int end) { + if (start >= end) { + return 0; + } + int mid = start + (end - start) / 2; + int cnt = mergeSort(nums, start, mid) + mergeSort(nums, mid + 1, end); + for (int i = start; i <= mid; i++) { + // it has to be 2.0 instead of 2, otherwise it's going to stack overflow, i.e. test3 is + // going to fail + int j = mid + 1; + while (j <= end && nums[i] > nums[j] * 2.0) { + j++; + } + cnt += j - (mid + 1); + } + Arrays.sort(nums, start, end + 1); + return cnt; + } +} diff --git a/src/main/java/g0401_0500/s0493_reverse_pairs/readme.md b/src/main/java/g0401_0500/s0493_reverse_pairs/readme.md new file mode 100644 index 000000000..fe1cb2e74 --- /dev/null +++ b/src/main/java/g0401_0500/s0493_reverse_pairs/readme.md @@ -0,0 +1,24 @@ +493\. Reverse Pairs + +Hard + +Given an integer array `nums`, return _the number of **reverse pairs** in the array_. + +A reverse pair is a pair `(i, j)` where `0 <= i < j < nums.length` and `nums[i] > 2 * nums[j]`. + +**Example 1:** + +**Input:** nums = [1,3,2,3,1] + +**Output:** 2 + +**Example 2:** + +**Input:** nums = [2,4,3,5,1] + +**Output:** 3 + +**Constraints:** + +* 1 <= nums.length <= 5 * 104 +* -231 <= nums[i] <= 231 - 1 \ No newline at end of file diff --git a/src/main/java/g0401_0500/s0495_teemo_attacking/Solution.java b/src/main/java/g0401_0500/s0495_teemo_attacking/Solution.java new file mode 100644 index 000000000..ea1c68d21 --- /dev/null +++ b/src/main/java/g0401_0500/s0495_teemo_attacking/Solution.java @@ -0,0 +1,25 @@ +package g0401_0500.s0495_teemo_attacking; + +// #Easy #Array #Simulation + +public class Solution { + public int findPoisonedDuration(int[] timeSeries, int duration) { + if (duration == 0) { + return 0; + } + int start = timeSeries[0]; + int end = timeSeries[0] + duration - 1; + int poisonDuration = end - start + 1; + for (int i = 1; i < timeSeries.length; i++) { + if (timeSeries[i] <= end) { + poisonDuration += (duration - (end - timeSeries[i] + 1)); + end += (duration - (end - timeSeries[i] + 1)); + } else { + start = timeSeries[i]; + end = timeSeries[i] + duration - 1; + poisonDuration += end - start + 1; + } + } + return poisonDuration; + } +} diff --git a/src/main/java/g0401_0500/s0495_teemo_attacking/readme.md b/src/main/java/g0401_0500/s0495_teemo_attacking/readme.md new file mode 100644 index 000000000..d04e932ff --- /dev/null +++ b/src/main/java/g0401_0500/s0495_teemo_attacking/readme.md @@ -0,0 +1,37 @@ +495\. Teemo Attacking + +Easy + +Our hero Teemo is attacking an enemy Ashe with poison attacks! When Teemo attacks Ashe, Ashe gets poisoned for a exactly `duration` seconds. More formally, an attack at second `t` will mean Ashe is poisoned during the **inclusive** time interval `[t, t + duration - 1]`. If Teemo attacks again **before** the poison effect ends, the timer for it is **reset**, and the poison effect will end `duration` seconds after the new attack. + +You are given a **non-decreasing** integer array `timeSeries`, where `timeSeries[i]` denotes that Teemo attacks Ashe at second `timeSeries[i]`, and an integer `duration`. + +Return _the **total** number of seconds that Ashe is poisoned_. + +**Example 1:** + +**Input:** timeSeries = [1,4], duration = 2 + +**Output:** 4 + +**Explanation:** Teemo's attacks on Ashe go as follows: - At second 1, Teemo attacks, and Ashe is poisoned for seconds 1 and 2. - At second 4, Teemo attacks, and Ashe is poisoned for seconds 4 and 5. Ashe is poisoned for seconds 1, 2, 4, and 5, which is 4 seconds in total. + +**Example 2:** + +**Input:** timeSeries = [1,2], duration = 2 + +**Output:** 3 + +**Explanation:** + +Teemo's attacks on Ashe go as follows: + +- At second 1, Teemo attacks, and Ashe is poisoned for seconds 1 and 2. + +- At second 2 however, Teemo attacks again and resets the poison timer. Ashe is poisoned for seconds 2 and 3. Ashe is poisoned for seconds 1, 2, and 3, which is 3 seconds in total. + +**Constraints:** + +* 1 <= timeSeries.length <= 104 +* 0 <= timeSeries[i], duration <= 107 +* `timeSeries` is sorted in **non-decreasing** order. \ No newline at end of file diff --git a/src/main/java/g0401_0500/s0496_next_greater_element_i/Solution.java b/src/main/java/g0401_0500/s0496_next_greater_element_i/Solution.java new file mode 100644 index 000000000..f3c780993 --- /dev/null +++ b/src/main/java/g0401_0500/s0496_next_greater_element_i/Solution.java @@ -0,0 +1,38 @@ +package g0401_0500.s0496_next_greater_element_i; + +// #Easy #Array #Hash_Table #Stack #Monotonic_Stack + +import java.util.HashMap; +import java.util.Map; + +public class Solution { + public int[] nextGreaterElement(int[] nums1, int[] nums2) { + Map indexMap = new HashMap<>(); + for (int i = 0; i < nums2.length; i++) { + indexMap.put(nums2[i], i); + } + + for (int i = 0; i < nums1.length; i++) { + int num = nums1[i]; + int index = indexMap.get(num); + if (index == nums2.length - 1) { + nums1[i] = -1; + } else { + boolean found = false; + while (index < nums2.length) { + if (nums2[index] > num) { + nums1[i] = nums2[index]; + found = true; + break; + } + index++; + } + if (!found) { + nums1[i] = -1; + } + } + } + + return nums1; + } +} diff --git a/src/main/java/g0401_0500/s0496_next_greater_element_i/readme.md b/src/main/java/g0401_0500/s0496_next_greater_element_i/readme.md new file mode 100644 index 000000000..ce964c577 --- /dev/null +++ b/src/main/java/g0401_0500/s0496_next_greater_element_i/readme.md @@ -0,0 +1,50 @@ +496\. Next Greater Element I + +Easy + +The **next greater element** of some element `x` in an array is the **first greater** element that is **to the right** of `x` in the same array. + +You are given two **distinct 0-indexed** integer arrays `nums1` and `nums2`, where `nums1` is a subset of `nums2`. + +For each `0 <= i < nums1.length`, find the index `j` such that `nums1[i] == nums2[j]` and determine the **next greater element** of `nums2[j]` in `nums2`. If there is no next greater element, then the answer for this query is `-1`. + +Return _an array_ `ans` _of length_ `nums1.length` _such that_ `ans[i]` _is the **next greater element** as described above._ + +**Example 1:** + +**Input:** nums1 = [4,1,2], nums2 = [1,3,4,2] + +**Output:** [-1,3,-1] + +**Explanation:** + +The next greater element for each value of nums1 is as follows: + +- 4 is underlined in nums2 = [1,3,4,2]. There is no next greater element, so the answer is -1. + +- 1 is underlined in nums2 = [1,3,4,2]. The next greater element is 3. + +- 2 is underlined in nums2 = [1,3,4,2]. There is no next greater element, so the answer is -1. + +**Example 2:** + +**Input:** nums1 = [2,4], nums2 = [1,2,3,4] + +**Output:** [3,-1] + +**Explanation:** + +The next greater element for each value of nums1 is as follows: + +- 2 is underlined in nums2 = [1,2,3,4]. The next greater element is 3. + +- 4 is underlined in nums2 = [1,2,3,4]. There is no next greater element, so the answer is -1. + +**Constraints:** + +* `1 <= nums1.length <= nums2.length <= 1000` +* 0 <= nums1[i], nums2[i] <= 104 +* All integers in `nums1` and `nums2` are **unique**. +* All the integers of `nums1` also appear in `nums2`. + +**Follow up:** Could you find an `O(nums1.length + nums2.length)` solution? \ No newline at end of file diff --git a/src/main/java/g0401_0500/s0497_random_point_in_non_overlapping_rectangles/Solution.java b/src/main/java/g0401_0500/s0497_random_point_in_non_overlapping_rectangles/Solution.java new file mode 100644 index 000000000..3c6c5d624 --- /dev/null +++ b/src/main/java/g0401_0500/s0497_random_point_in_non_overlapping_rectangles/Solution.java @@ -0,0 +1,53 @@ +package g0401_0500.s0497_random_point_in_non_overlapping_rectangles; + +// #Medium #Math #Binary_Search #Prefix_Sum #Ordered_Set #Randomized #Reservoir_Sampling + +import java.security.SecureRandom; + +public class Solution { + private final int[] weights; + private final int[][] rects; + private final SecureRandom random; + + public Solution(int[][] rects) { + this.weights = new int[rects.length]; + this.rects = rects; + this.random = new SecureRandom(); + for (int i = 0; i < rects.length; i++) { + int[] rect = rects[i]; + int count = (1 + rect[2] - rect[0]) * (1 + rect[3] - rect[1]); + weights[i] = (i == 0 ? 0 : weights[i - 1]) + count; + } + } + + public int[] pick() { + int picked = 1 + random.nextInt(weights[weights.length - 1]); + int idx = findGreaterOrEqual(picked); + return getRandomPoint(idx); + } + + private int findGreaterOrEqual(int target) { + int left = 0; + int right = weights.length - 1; + while (left + 1 < right) { + int mid = left + (right - left) / 2; + if (weights[mid] >= target) { + right = mid; + } else { + left = mid + 1; + } + } + return weights[left] >= target ? left : right; + } + + private int[] getRandomPoint(int idx) { + int[] r = rects[idx]; + int left = r[0]; + int right = r[2]; + int bot = r[1]; + int top = r[3]; + return new int[] { + left + random.nextInt(right - left + 1), bot + random.nextInt(top - bot + 1) + }; + } +} diff --git a/src/main/java/g0401_0500/s0497_random_point_in_non_overlapping_rectangles/readme.md b/src/main/java/g0401_0500/s0497_random_point_in_non_overlapping_rectangles/readme.md new file mode 100644 index 000000000..dfd450512 --- /dev/null +++ b/src/main/java/g0401_0500/s0497_random_point_in_non_overlapping_rectangles/readme.md @@ -0,0 +1,42 @@ +497\. Random Point in Non-overlapping Rectangles + +Medium + +You are given an array of non-overlapping axis-aligned rectangles `rects` where rects[i] = [ai, bi, xi, yi] indicates that (ai, bi) is the bottom-left corner point of the ith rectangle and (xi, yi) is the top-right corner point of the ith rectangle. Design an algorithm to pick a random integer point inside the space covered by one of the given rectangles. A point on the perimeter of a rectangle is included in the space covered by the rectangle. + +Any integer point inside the space covered by one of the given rectangles should be equally likely to be returned. + +**Note** that an integer point is a point that has integer coordinates. + +Implement the `Solution` class: + +* `Solution(int[][] rects)` Initializes the object with the given rectangles `rects`. +* `int[] pick()` Returns a random integer point `[u, v]` inside the space covered by one of the given rectangles. + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2021/07/24/lc-pickrandomrec.jpg) + +**Input** ["Solution", "pick", "pick", "pick", "pick", "pick"] [[[[-2, -2, 1, 1], [2, 2, 4, 6]]], [], [], [], [], []] + +**Output:** [null, [1, -2], [1, -1], [-1, -2], [-2, -2], [0, 0]] + +**Explanation:** + + Solution solution = new Solution([[-2, -2, 1, 1], [2, 2, 4, 6]]); + solution.pick(); // return [1, -2] + solution.pick(); // return [1, -1] + solution.pick(); // return [-1, -2] + solution.pick(); // return [-2, -2] + solution.pick(); // return [0, 0] + +**Constraints:** + +* `1 <= rects.length <= 100` +* `rects[i].length == 4` +* -109 <= ai < xi <= 109 +* -109 <= bi < yi <= 109 +* xi - ai <= 2000 +* yi - bi <= 2000 +* All the rectangles do not overlap. +* At most 104 calls will be made to `pick`. \ No newline at end of file diff --git a/src/test/java/g0401_0500/s0492_construct_the_rectangle/SolutionTest.java b/src/test/java/g0401_0500/s0492_construct_the_rectangle/SolutionTest.java new file mode 100644 index 000000000..41be42121 --- /dev/null +++ b/src/test/java/g0401_0500/s0492_construct_the_rectangle/SolutionTest.java @@ -0,0 +1,23 @@ +package g0401_0500.s0492_construct_the_rectangle; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void constructRectangle() { + assertThat(new Solution().constructRectangle(4), equalTo(new int[] {2, 2})); + } + + @Test + void constructRectangle2() { + assertThat(new Solution().constructRectangle(37), equalTo(new int[] {37, 1})); + } + + @Test + void constructRectangle3() { + assertThat(new Solution().constructRectangle(122122), equalTo(new int[] {427, 286})); + } +} diff --git a/src/test/java/g0401_0500/s0493_reverse_pairs/SolutionTest.java b/src/test/java/g0401_0500/s0493_reverse_pairs/SolutionTest.java new file mode 100644 index 000000000..2f20a9289 --- /dev/null +++ b/src/test/java/g0401_0500/s0493_reverse_pairs/SolutionTest.java @@ -0,0 +1,18 @@ +package g0401_0500.s0493_reverse_pairs; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void reversePairs() { + assertThat(new Solution().reversePairs(new int[] {1, 3, 2, 3, 1}), equalTo(2)); + } + + @Test + void reversePairs2() { + assertThat(new Solution().reversePairs(new int[] {2, 4, 3, 5, 1}), equalTo(3)); + } +} diff --git a/src/test/java/g0401_0500/s0495_teemo_attacking/SolutionTest.java b/src/test/java/g0401_0500/s0495_teemo_attacking/SolutionTest.java new file mode 100644 index 000000000..4999a0af9 --- /dev/null +++ b/src/test/java/g0401_0500/s0495_teemo_attacking/SolutionTest.java @@ -0,0 +1,18 @@ +package g0401_0500.s0495_teemo_attacking; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void findPoisonedDuration() { + assertThat(new Solution().findPoisonedDuration(new int[] {1, 4}, 2), equalTo(4)); + } + + @Test + void findPoisonedDuration2() { + assertThat(new Solution().findPoisonedDuration(new int[] {1, 2}, 2), equalTo(3)); + } +} diff --git a/src/test/java/g0401_0500/s0496_next_greater_element_i/SolutionTest.java b/src/test/java/g0401_0500/s0496_next_greater_element_i/SolutionTest.java new file mode 100644 index 000000000..d4097fa6d --- /dev/null +++ b/src/test/java/g0401_0500/s0496_next_greater_element_i/SolutionTest.java @@ -0,0 +1,22 @@ +package g0401_0500.s0496_next_greater_element_i; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void nextGreaterElement() { + assertThat( + new Solution().nextGreaterElement(new int[] {4, 1, 2}, new int[] {1, 3, 4, 2}), + equalTo(new int[] {-1, 3, -1})); + } + + @Test + void nextGreaterElement2() { + assertThat( + new Solution().nextGreaterElement(new int[] {2, 4}, new int[] {1, 2, 3, 4}), + equalTo(new int[] {3, -1})); + } +} diff --git a/src/test/java/g0401_0500/s0497_random_point_in_non_overlapping_rectangles/SolutionTest.java b/src/test/java/g0401_0500/s0497_random_point_in_non_overlapping_rectangles/SolutionTest.java new file mode 100644 index 000000000..bf75651df --- /dev/null +++ b/src/test/java/g0401_0500/s0497_random_point_in_non_overlapping_rectangles/SolutionTest.java @@ -0,0 +1,20 @@ +package g0401_0500.s0497_random_point_in_non_overlapping_rectangles; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import com_github_leetcode.CommonUtils; +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void solutionTest() { + Solution solution = new Solution(new int[][] {{-2, -2, 1, 1}, {2, 2, 4, 6}}); + CommonUtils.printArray(solution.pick()); + CommonUtils.printArray(solution.pick()); + CommonUtils.printArray(solution.pick()); + CommonUtils.printArray(solution.pick()); + CommonUtils.printArray(solution.pick()); + assertThat(true, equalTo(true)); + } +}