Longest Increasing Subsequence Algorithm
The Longest Increasing Subsequence (LIS) algorithm is a dynamic programming technique used to solve the problem of finding the longest increasing subsequence in a given sequence of numbers. An increasing subsequence is a subsequence of a given sequence in which the elements are in strictly increasing order. The primary objective of the LIS algorithm is to find the longest subsequence of elements that are in an increasing order, which could be either consecutive or non-consecutive within the original sequence.
The algorithm works by employing a bottom-up approach, starting at the first element in the sequence and gradually building the solution for each subsequent element. It maintains an auxiliary table to store the longest increasing subsequence ending at each position in the input sequence. This table is updated iteratively by comparing the current element with all the previous elements in the sequence. If the current element is greater than a previous element, the length of the longest increasing subsequence ending at the current element is updated based on the previous element's value in the auxiliary table. This process is repeated for each element in the sequence, and the maximum value in the auxiliary table represents the length of the longest increasing subsequence. This algorithm has a time complexity of O(n^2), where n is the number of elements in the input sequence.
package DynamicProgramming;
import java.util.Scanner;
/**
* @author Afrizal Fikri (https://github.com/icalF)
*/
public class LongestIncreasingSubsequence {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int ar[] = new int[n];
for (int i = 0; i < n; i++) {
ar[i] = sc.nextInt();
}
System.out.println(LIS(ar));
sc.close();
}
private static int upperBound(int[] ar, int l, int r, int key) {
while (l < r - 1) {
int m = (l + r) >>> 1;
if (ar[m] >= key)
r = m;
else
l = m;
}
return r;
}
private static int LIS(int[] array) {
int N = array.length;
if (N == 0)
return 0;
int[] tail = new int[N];
// always points empty slot in tail
int length = 1;
tail[0] = array[0];
for (int i = 1; i < N; i++) {
// new smallest value
if (array[i] < tail[0])
tail[0] = array[i];
// array[i] extends largest subsequence
else if (array[i] > tail[length - 1])
tail[length++] = array[i];
// array[i] will become end candidate of an existing subsequence or
// Throw away larger elements in all LIS, to make room for upcoming grater elements than array[i]
// (and also, array[i] would have already appeared in one of LIS, identify the location and replace it)
else
tail[upperBound(tail, -1, length - 1, array[i])] = array[i];
}
return length;
}
}