diff --git a/src/algorithms/sets/longest-increasing-subsequence/__test__/longestIncreasingSubsequence.test.js b/src/algorithms/sets/longest-increasing-subsequence/__test__/longestIncreasingSubsequence.test.js
new file mode 100644
index 0000000000..4a444a895a
--- /dev/null
+++ b/src/algorithms/sets/longest-increasing-subsequence/__test__/longestIncreasingSubsequence.test.js
@@ -0,0 +1,36 @@
+import longestIncreasingSubsequence from '../longestIncreasingSubsequence';
+
+describe('LongestIncreasingSubsequence', () => {
+  it('should find longest increasing subsequence length', () => {
+    // Should be:
+    // 9 or
+    // 8 or
+    // 7 or
+    // 6 or
+    // ...
+    expect(longestIncreasingSubsequence([
+      9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
+    ])).toBe(1);
+
+    // Should be:
+    // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
+    expect(longestIncreasingSubsequence([
+      0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+    ])).toBe(10);
+
+    // Should be:
+    // -1, 0, 2, 3
+    expect(longestIncreasingSubsequence([
+      3, 4, -1, 0, 6, 2, 3,
+    ])).toBe(4);
+
+    // Should be:
+    // 0, 2, 6, 9, 11, 15 or
+    // 0, 4, 6, 9, 11, 15 or
+    // 0, 2, 6, 9, 13, 15 or
+    // 0, 4, 6, 9, 13, 15
+    expect(longestIncreasingSubsequence([
+      0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15,
+    ])).toBe(6);
+  });
+});
diff --git a/src/algorithms/sets/longest-increasing-subsequence/longestIncreasingSubsequence.js b/src/algorithms/sets/longest-increasing-subsequence/longestIncreasingSubsequence.js
new file mode 100644
index 0000000000..88e97accea
--- /dev/null
+++ b/src/algorithms/sets/longest-increasing-subsequence/longestIncreasingSubsequence.js
@@ -0,0 +1,28 @@
+/**
+ * Efficient approach to find longest increasing subsequence.
+ * Complexity: O(n * log(n))
+ *
+ * @param {number[]} sequence
+ * @return {number}
+ */
+export default function LongestIncreasingSubsequence(sequence) {
+  // Retrieves the smallest number greater or equal to val in sorted arr.
+  function upperBound(arr, val) {
+    let lo = 0;
+    let hi = arr.length;
+
+    while (lo < hi) {
+      const mid = lo + Math.floor((hi - lo) / 2);
+      if (arr[mid] < val) {
+        lo = mid + 1;
+      } else {
+        hi = mid;
+      }
+    }
+    return hi;
+  }
+
+  const lis = [];
+  sequence.forEach((val) => { lis[upperBound(lis, val)] = val; });
+  return lis.length;
+}