forked from TheAlgorithms/Java
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLongestIncreasingSubsequenceNLogN.java
75 lines (64 loc) · 2.42 KB
/
LongestIncreasingSubsequenceNLogN.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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;
}
}