mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-06 17:29:31 +08:00
Add LongestIncreasingSubsequenceNLogN (#6221)
This commit is contained in:
@ -0,0 +1,75 @@
|
||||
package com.thealgorithms.dynamicprogramming;
|
||||
|
||||
/**
|
||||
* Implementation of the Longest Increasing Subsequence (LIS) problem using
|
||||
* an O(n log n) dynamic programming solution enhanced with binary search.
|
||||
*
|
||||
* @author Vusal Huseynov (https://github.com/huseynovvusal)
|
||||
*/
|
||||
public final class LongestIncreasingSubsequenceNLogN {
|
||||
private LongestIncreasingSubsequenceNLogN() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the index of the smallest element in the array that is greater than
|
||||
* or equal to the target using binary search. The search is restricted to
|
||||
* the first `size` elements of the array.
|
||||
*
|
||||
* @param arr The array to search in (assumed to be sorted up to `size`).
|
||||
* @param size The number of valid elements in the array.
|
||||
* @param target The target value to find the lower bound for.
|
||||
* @return The index of the lower bound.
|
||||
*/
|
||||
private static int lowerBound(int[] arr, int target, int size) {
|
||||
int l = 0;
|
||||
int r = size;
|
||||
|
||||
while (l < r) {
|
||||
int mid = l + (r - l) / 2;
|
||||
|
||||
if (target > arr[mid]) {
|
||||
// Move right if target is greater than mid element
|
||||
l = mid + 1;
|
||||
} else {
|
||||
// Move left if target is less than or equal to mid element
|
||||
r = mid;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the index where the target can be inserted
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the length of the Longest Increasing Subsequence (LIS) in the given array.
|
||||
*
|
||||
* @param arr The input array of integers.
|
||||
* @return The length of the LIS.
|
||||
*/
|
||||
public static int lengthOfLIS(int[] arr) {
|
||||
if (arr == null || arr.length == 0) {
|
||||
return 0; // Return 0 for empty or null arrays
|
||||
}
|
||||
|
||||
// tails[i] - the smallest end element of an increasing subsequence of length i+1
|
||||
int[] tails = new int[arr.length];
|
||||
// size - the length of the longest increasing subsequence found so far
|
||||
int size = 0;
|
||||
|
||||
for (int x : arr) {
|
||||
// Find the position to replace or extend the subsequence
|
||||
int index = lowerBound(tails, x, size);
|
||||
|
||||
// Update the tails array with the current element
|
||||
tails[index] = x;
|
||||
|
||||
// If the element extends the subsequence, increase the size
|
||||
if (index == size) {
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the length of the LIS
|
||||
return size;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user