diff --git a/search/Longest_Increasing_Subsequence_using_binary_search.cpp b/search/Longest_Increasing_Subsequence_using_binary_search.cpp new file mode 100644 index 00000000000..2f83de72ecf --- /dev/null +++ b/search/Longest_Increasing_Subsequence_using_binary_search.cpp @@ -0,0 +1,117 @@ +/** + * @file + * @brief find the length of the Longest Increasing Subsequence (LIS) + * using [Binary Search](https://en.wikipedia.org/wiki/Longest_increasing_subsequence) + * @details + * Given an integer array nums, return the length of the longest strictly + * increasing subsequence. + * The longest increasing subsequence is described as a subsequence of an array + * where: All elements of the subsequence are in increasing order. This subsequence + * itself is of the longest length possible. + + * For solving this problem we have Three Approaches :- + + * Approach 1 :- Using Brute Force + * The first approach that came to your mind is the Brute Force approach where we + * generate all subsequences and then manually filter the subsequences whose + * elements come in increasing order and then return the longest such subsequence. + * Time Complexity :- O(2^n) + * It's time complexity is exponential. Therefore we will try some other + * approaches. + + * Approach 2 :- Using Dynamic Programming + * To generate all subsequences we will use recursion and in the recursive logic we + * will figure out a way to solve this problem. Recursive Logic to solve this + * problem:- + * 1. We only consider the element in the subsequence if the element is grater then + * the last element present in the subsequence + * 2. When we consider the element we will increase the length of subsequence by 1 + * Time Complexity: O(N*N) + * Space Complexity: O(N*N) + O(N) + + * This approach is better then the previous Brute Force approach so, we can + * consider this approach. + + * But when the Constraints for the problem is very larger then this approach fails + + * Approach 3 :- Using Binary Search + * Other approaches use additional space to create a new subsequence Array. + * Instead, this solution uses the existing nums Array to build the subsequence + * array. We can do this because the length of the subsequence array will never be + * longer than the current index. + + * Time complexity: O(n∗log(n)) + * Space complexity: O(1) + + * This approach consider Most optimal Approach for solving this problem + + * @author [Naman Jain](https://github.com/namanmodi65) + */ + +#include /// for std::assert +#include /// for IO operations +#include /// for std::vector +#include /// for std::lower_bound +#include /// for std::uint32_t + +/** + * @brief Function to find the length of the Longest Increasing Subsequence (LIS) + * using Binary Search + * @tparam T The type of the elements in the input vector + * @param nums The input vector of elements of type T + * @return The length of the longest increasing subsequence + */ +template +std::uint32_t longest_increasing_subsequence_using_binary_search(std::vector& nums) { + if (nums.empty()) return 0; + + std::vector ans; + ans.push_back(nums[0]); + for (std::size_t i = 1; i < nums.size(); i++) { + if (nums[i] > ans.back()) { + ans.push_back(nums[i]); + } else { + auto idx = std::lower_bound(ans.begin(), ans.end(), nums[i]) - ans.begin(); + ans[idx] = nums[i]; + } + } + return static_cast(ans.size()); +} + +/** + * @brief Test cases for Longest Increasing Subsequence function + * @returns void + */ +static void tests() { + std::vector arr = {10, 9, 2, 5, 3, 7, 101, 18}; + assert(longest_increasing_subsequence_using_binary_search(arr) == 4); + + std::vector arr2 = {0, 1, 0, 3, 2, 3}; + assert(longest_increasing_subsequence_using_binary_search(arr2) == 4); + + std::vector arr3 = {7, 7, 7, 7, 7, 7, 7}; + assert(longest_increasing_subsequence_using_binary_search(arr3) == 1); + + std::vector arr4 = {-10, -1, -5, 0, 5, 1, 2}; + assert(longest_increasing_subsequence_using_binary_search(arr4) == 5); + + std::vector arr5 = {3.5, 1.2, 2.8, 3.1, 4.0}; + assert(longest_increasing_subsequence_using_binary_search(arr5) == 4); + + std::vector arr6 = {'a', 'b', 'c', 'a', 'd'}; + assert(longest_increasing_subsequence_using_binary_search(arr6) == 4); + + std::vector arr7 = {}; + assert(longest_increasing_subsequence_using_binary_search(arr7) == 0); + + std::cout << "All tests have successfully passed!\n"; +} + +/** + * @brief Main function to run tests + * @returns 0 on exit + */ +int main() { + tests(); // run self test implementation + return 0; +}