From 68520bf14049c56578ca2b3d2cc3ec82c9a612ec Mon Sep 17 00:00:00 2001 From: ThanhNIT Date: Fri, 17 Dec 2021 17:25:50 +0700 Subject: [PATCH 1/2] Added tasks 374, 378, 380 --- .../Solution.java | 34 +++++++++++ .../readme.md | 46 +++++++++++++++ .../Solution.java | 56 ++++++++++++++++++ .../readme.md | 36 +++++++++++ .../RandomizedSet.java | 59 +++++++++++++++++++ .../readme.md | 35 +++++++++++ .../SolutionTest.java | 28 +++++++++ .../SolutionTest.java | 20 +++++++ .../RandomizedSetTest.java | 38 ++++++++++++ 9 files changed, 352 insertions(+) create mode 100644 src/main/java/g0301_0400/s0374_guess_number_higher_or_lower/Solution.java create mode 100644 src/main/java/g0301_0400/s0374_guess_number_higher_or_lower/readme.md create mode 100644 src/main/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/Solution.java create mode 100644 src/main/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/readme.md create mode 100644 src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSet.java create mode 100644 src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/readme.md create mode 100644 src/test/java/g0301_0400/s0374_guess_number_higher_or_lower/SolutionTest.java create mode 100644 src/test/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/SolutionTest.java create mode 100644 src/test/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSetTest.java diff --git a/src/main/java/g0301_0400/s0374_guess_number_higher_or_lower/Solution.java b/src/main/java/g0301_0400/s0374_guess_number_higher_or_lower/Solution.java new file mode 100644 index 000000000..a682e6399 --- /dev/null +++ b/src/main/java/g0301_0400/s0374_guess_number_higher_or_lower/Solution.java @@ -0,0 +1,34 @@ +package g0301_0400.s0374_guess_number_higher_or_lower; + +// #Easy #Binary_Search #Interactive + +/** + * Forward declaration of guess API. + * + * @param num your guess + * @return -1 if num is lower than the guess number 1 if num is higher than the guess number + * otherwise return 0 int guess(int num); + */ +public class Solution { + public int guessNumber(int n) { + int left = 1; + int right = n; + int mid; + while (left <= right) { + mid = left + (right - left) / 2; + if (guess(mid) == 1) { + left = mid + 1; + } else if (guess(mid) == -1) { + right = mid - 1; + } else { + return mid; + } + } + return -1; + } + + // Assume we pick 7 + private int guess(int num) { + return Integer.compare(7, num); + } +} diff --git a/src/main/java/g0301_0400/s0374_guess_number_higher_or_lower/readme.md b/src/main/java/g0301_0400/s0374_guess_number_higher_or_lower/readme.md new file mode 100644 index 000000000..17b675e9d --- /dev/null +++ b/src/main/java/g0301_0400/s0374_guess_number_higher_or_lower/readme.md @@ -0,0 +1,46 @@ +374\. Guess Number Higher or Lower + +Easy + +We are playing the Guess Game. The game is as follows: + +I pick a number from `1` to `n`. You have to guess which number I picked. + +Every time you guess wrong, I will tell you whether the number I picked is higher or lower than your guess. + +You call a pre-defined API `int guess(int num)`, which returns 3 possible results: + +* `-1`: The number I picked is lower than your guess (i.e. `pick < num`). +* `1`: The number I picked is higher than your guess (i.e. `pick > num`). +* `0`: The number I picked is equal to your guess (i.e. `pick == num`). + +Return _the number that I picked_. + +**Example 1:** + +**Input:** n = 10, pick = 6 + +**Output:** 6 + +**Example 2:** + +**Input:** n = 1, pick = 1 + +**Output:** 1 + +**Example 3:** + +**Input:** n = 2, pick = 1 + +**Output:** 1 + +**Example 4:** + +**Input:** n = 2, pick = 2 + +**Output:** 2 + +**Constraints:** + +* 1 <= n <= 231 - 1 +* `1 <= pick <= n` \ No newline at end of file diff --git a/src/main/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/Solution.java b/src/main/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/Solution.java new file mode 100644 index 000000000..2010c8f51 --- /dev/null +++ b/src/main/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/Solution.java @@ -0,0 +1,56 @@ +package g0301_0400.s0378_kth_smallest_element_in_a_sorted_matrix; + +// #Medium #Top_Interview_Questions #Array #Sorting #Binary_Search #Matrix #Heap_Priority_Queue + +public class Solution { + public int kthSmallest(int[][] matrix, int k) { + if (matrix == null || matrix.length == 0) { + return -1; + } + int start = matrix[0][0]; + int end = matrix[matrix.length - 1][matrix[0].length - 1]; + // O(log(max-min)) time + while (start + 1 < end) { + int mid = start + (end - start) / 2; + if (countLessEqual(matrix, mid) < k) { + // look towards end + start = mid; + } else { + // look towards start + end = mid; + } + } + + // leave only with start and end, one of them must be the answer + // try to see if start fits the criteria first + if (countLessEqual(matrix, start) >= k) { + return start; + } else { + return end; + } + } + + // countLessEqual + // O(n) Time + private int countLessEqual(int[][] matrix, int target) { + // binary elimination from top right + int row = 0; + int col = matrix[0].length - 1; + int count = 0; + while (row < matrix.length && col >= 0) { + if (matrix[row][col] == target) { + // get the count in current row + count += col + 1; + row++; + } else if (matrix[row][col] > target) { + // eliminate the current col + col--; + } else { + // get the count in current row + count += col + 1; + row++; + } + } + return count; + } +} diff --git a/src/main/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/readme.md b/src/main/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/readme.md new file mode 100644 index 000000000..85803a3c0 --- /dev/null +++ b/src/main/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/readme.md @@ -0,0 +1,36 @@ +378\. Kth Smallest Element in a Sorted Matrix + +Medium + +Given an `n x n` `matrix` where each of the rows and columns is sorted in ascending order, return _the_ kth _smallest element in the matrix_. + +Note that it is the kth smallest element **in the sorted order**, not the kth **distinct** element. + +You must find a solution with a memory complexity better than O(n2). + +**Example 1:** + +**Input:** matrix = \[\[1,5,9\],\[10,11,13\],\[12,13,15\]\], k = 8 + +**Output:** 13 + +**Explanation:** The elements in the matrix are \[1,5,9,10,11,12,13,**13**,15\], and the 8th smallest number is 13 + +**Example 2:** + +**Input:** matrix = \[\[-5\]\], k = 1 + +**Output:** -5 + +**Constraints:** + +* `n == matrix.length == matrix[i].length` +* `1 <= n <= 300` +* -109 <= matrix[i][j] <= 109 +* All the rows and columns of `matrix` are **guaranteed** to be sorted in **non-decreasing order**. +* 1 <= k <= n2 + +**Follow up:** + +* Could you solve the problem with a constant memory (i.e., `O(1)` memory complexity)? +* Could you solve the problem in `O(n)` time complexity? The solution may be too advanced for an interview but you may find reading [this paper](http://www.cse.yorku.ca/~andy/pubs/X+Y.pdf) fun. \ No newline at end of file diff --git a/src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSet.java b/src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSet.java new file mode 100644 index 000000000..5c8f675c7 --- /dev/null +++ b/src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSet.java @@ -0,0 +1,59 @@ +package g0301_0400.s0380_insert_delete_getrandom_o1; + +import java.util.*; + +class RandomizedSet { + private final Random rand; + private final List list; + private final Map map; + + /** Initialize your data structure here. */ + public RandomizedSet() { + this.rand = new Random(); + this.list = new ArrayList<>(); + this.map = new HashMap<>(); + } + + /** + * Inserts a value to the set. Returns true if the set did not already contain the specified + * element. + */ + public boolean insert(int val) { + if (this.map.containsKey(val)) { + return false; + } + this.list.add(val); + this.map.put(val, list.size() - 1); + return true; + } + + /** Removes a value from the set. Returns true if the set contained the specified element. */ + public boolean remove(int val) { + if (!this.map.containsKey(val)) { + return false; + } + int index = this.map.get(val); + if (index == this.list.size() - 1) { + this.list.remove(index); + this.map.remove(val); + return true; + } + int value = list.get(list.size() - 1); + this.list.set(index, value); + this.list.remove(this.list.size() - 1); + this.map.remove(val); + this.map.put(value, index); + return true; + } + + /** Get a random element from the set. */ + public int getRandom() { + return this.list.get(rand.nextInt(list.size())); + } +} + +/** + * Your RandomizedSet object will be instantiated and called as such: RandomizedSet obj = new + * RandomizedSet(); boolean param_1 = obj.insert(val); boolean param_2 = obj.remove(val); int + * param_3 = obj.getRandom(); + */ diff --git a/src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/readme.md b/src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/readme.md new file mode 100644 index 000000000..de379c6a4 --- /dev/null +++ b/src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/readme.md @@ -0,0 +1,35 @@ +380\. Insert Delete GetRandom O(1) + +Medium + +Implement the `RandomizedSet` class: + +* `RandomizedSet()` Initializes the `RandomizedSet` object. +* `bool insert(int val)` Inserts an item `val` into the set if not present. Returns `true` if the item was not present, `false` otherwise. +* `bool remove(int val)` Removes an item `val` from the set if present. Returns `true` if the item was present, `false` otherwise. +* `int getRandom()` Returns a random element from the current set of elements (it's guaranteed that at least one element exists when this method is called). Each element must have the **same probability** of being returned. + +You must implement the functions of the class such that each function works in **average** `O(1)` time complexity. + +**Example 1:** + +**Input** \["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"\] \[\[\], \[1\], \[2\], \[2\], \[\], \[1\], \[2\], \[\]\] + +**Output:** \[null, true, false, true, 2, true, false, 2\] + +**Explanation:** + + RandomizedSet randomizedSet = new RandomizedSet(); + randomizedSet.insert(1); // Inserts 1 to the set. Returns true as 1 was inserted successfully. + randomizedSet.remove(2); // Returns false as 2 does not exist in the set. + randomizedSet.insert(2); // Inserts 2 to the set, returns true. Set now contains \[1,2\]. + randomizedSet.getRandom(); // getRandom() should return either 1 or 2 randomly. + randomizedSet.remove(1); // Removes 1 from the set, returns true. Set now contains \[2\]. + randomizedSet.insert(2); // 2 was already in the set, so return false. + randomizedSet.getRandom(); // Since 2 is the only number in the set, getRandom() will always return 2. + +**Constraints:** + +* -231 <= val <= 231 - 1 +* At most `2 * `105 calls will be made to `insert`, `remove`, and `getRandom`. +* There will be **at least one** element in the data structure when `getRandom` is called. \ No newline at end of file diff --git a/src/test/java/g0301_0400/s0374_guess_number_higher_or_lower/SolutionTest.java b/src/test/java/g0301_0400/s0374_guess_number_higher_or_lower/SolutionTest.java new file mode 100644 index 000000000..51fc1bcff --- /dev/null +++ b/src/test/java/g0301_0400/s0374_guess_number_higher_or_lower/SolutionTest.java @@ -0,0 +1,28 @@ +package g0301_0400.s0374_guess_number_higher_or_lower; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void guessNumber() { + assertThat(new Solution().guessNumber(10), equalTo(7)); + } + + @Test + void guessNumber2() { + assertThat(new Solution().guessNumber(1), equalTo(-1)); + } + + @Test + void guessNumber3() { + assertThat(new Solution().guessNumber(2), equalTo(-1)); + } + + @Test + void guessNumber4() { + assertThat(new Solution().guessNumber(6), equalTo(-1)); + } +} diff --git a/src/test/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/SolutionTest.java b/src/test/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/SolutionTest.java new file mode 100644 index 000000000..c7e4a948b --- /dev/null +++ b/src/test/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/SolutionTest.java @@ -0,0 +1,20 @@ +package g0301_0400.s0378_kth_smallest_element_in_a_sorted_matrix; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void kthSmallest() { + assertThat( + new Solution().kthSmallest(new int[][] {{1, 5, 9}, {10, 11, 13}, {12, 13, 15}}, 8), + equalTo(13)); + } + + @Test + void kthSmallest2() { + assertThat(new Solution().kthSmallest(new int[][] {{-5}}, 1), equalTo(-5)); + } +} diff --git a/src/test/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSetTest.java b/src/test/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSetTest.java new file mode 100644 index 000000000..0793dcbdb --- /dev/null +++ b/src/test/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSetTest.java @@ -0,0 +1,38 @@ +package g0301_0400.s0380_insert_delete_getrandom_o1; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.Test; + +class RandomizedSetTest { + @Test + void RandomizedSet() { + List result = new ArrayList<>(); + RandomizedSet randomizedSet = null; + result.add(randomizedSet + ""); + randomizedSet = new RandomizedSet(); + result.add(randomizedSet.insert(1) + ""); + result.add(randomizedSet.remove(2) + ""); + result.add(randomizedSet.insert(2) + ""); + int random = randomizedSet.getRandom(); + result.add(random + ""); + result.add(randomizedSet.remove(1) + ""); + result.add(randomizedSet.insert(2) + ""); + result.add(randomizedSet.getRandom() + ""); + List expected = + new ArrayList<>( + Arrays.asList("null", "true", "false", "true", "1", "true", "false", "2")); + List expected2 = + new ArrayList<>( + Arrays.asList("null", "true", "false", "true", "2", "true", "false", "2")); + if (random == 1) { + assertThat(result, equalTo(expected)); + } else { + assertThat(result, equalTo(expected2)); + } + } +} From 2dd8e7820ec15977bf2449485bea62ae0c008d9d Mon Sep 17 00:00:00 2001 From: ThanhNIT Date: Fri, 17 Dec 2021 17:41:29 +0700 Subject: [PATCH 2/2] fix comments --- .../Solution.java | 6 +--- .../RandomizedSet.java | 29 +++++++++++-------- .../readme.md | 5 +++- .../RandomizedSetTest.java | 2 +- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/main/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/Solution.java b/src/main/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/Solution.java index 2010c8f51..431861b35 100644 --- a/src/main/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/Solution.java +++ b/src/main/java/g0301_0400/s0378_kth_smallest_element_in_a_sorted_matrix/Solution.java @@ -38,17 +38,13 @@ private int countLessEqual(int[][] matrix, int target) { int col = matrix[0].length - 1; int count = 0; while (row < matrix.length && col >= 0) { - if (matrix[row][col] == target) { + if (matrix[row][col] <= target) { // get the count in current row count += col + 1; row++; } else if (matrix[row][col] > target) { // eliminate the current col col--; - } else { - // get the count in current row - count += col + 1; - row++; } } return count; diff --git a/src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSet.java b/src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSet.java index 5c8f675c7..a979a2c6d 100644 --- a/src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSet.java +++ b/src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSet.java @@ -1,23 +1,28 @@ package g0301_0400.s0380_insert_delete_getrandom_o1; -import java.util.*; +// #Medium #Top_Interview_Questions #Array #Hash_Table #Math #Design #Randomized -class RandomizedSet { - private final Random rand; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class RandomizedSet { + private final SecureRandom rand; private final List list; private final Map map; - /** Initialize your data structure here. */ + // Initialize your data structure here. public RandomizedSet() { - this.rand = new Random(); + this.rand = new SecureRandom(); this.list = new ArrayList<>(); this.map = new HashMap<>(); } - /** - * Inserts a value to the set. Returns true if the set did not already contain the specified - * element. - */ + // Inserts a value to the set. Returns true if the set did not already contain the specified + // element. + public boolean insert(int val) { if (this.map.containsKey(val)) { return false; @@ -27,7 +32,7 @@ public boolean insert(int val) { return true; } - /** Removes a value from the set. Returns true if the set contained the specified element. */ + // Removes a value from the set. Returns true if the set contained the specified element. public boolean remove(int val) { if (!this.map.containsKey(val)) { return false; @@ -46,13 +51,13 @@ public boolean remove(int val) { return true; } - /** Get a random element from the set. */ + // Get a random element from the set. public int getRandom() { return this.list.get(rand.nextInt(list.size())); } } -/** +/* * Your RandomizedSet object will be instantiated and called as such: RandomizedSet obj = new * RandomizedSet(); boolean param_1 = obj.insert(val); boolean param_2 = obj.remove(val); int * param_3 = obj.getRandom(); diff --git a/src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/readme.md b/src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/readme.md index de379c6a4..d1e0c081c 100644 --- a/src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/readme.md +++ b/src/main/java/g0301_0400/s0380_insert_delete_getrandom_o1/readme.md @@ -13,7 +13,10 @@ You must implement the functions of the class such that each function works in * **Example 1:** -**Input** \["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"\] \[\[\], \[1\], \[2\], \[2\], \[\], \[1\], \[2\], \[\]\] +**Input** + + \["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"\] + \[\[\], \[1\], \[2\], \[2\], \[\], \[1\], \[2\], \[\]\] **Output:** \[null, true, false, true, 2, true, false, 2\] diff --git a/src/test/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSetTest.java b/src/test/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSetTest.java index 0793dcbdb..b47c9d07c 100644 --- a/src/test/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSetTest.java +++ b/src/test/java/g0301_0400/s0380_insert_delete_getrandom_o1/RandomizedSetTest.java @@ -10,7 +10,7 @@ class RandomizedSetTest { @Test - void RandomizedSet() { + void randomizedSet() { List result = new ArrayList<>(); RandomizedSet randomizedSet = null; result.add(randomizedSet + "");