diff --git a/src/algorithms/dynamic-programming/longestIncreasingSubsequence.js b/src/algorithms/dynamic-programming/longestIncreasingSubsequence.js
new file mode 100644
index 0000000..4a9cc1d
--- /dev/null
+++ b/src/algorithms/dynamic-programming/longestIncreasingSubsequence.js
@@ -0,0 +1,55 @@
+export function longestIncreasingSubsequenceSteps(arr = []) {
+ const n = arr.length;
+ const dp = Array(n).fill(1);
+ const parent = Array(n).fill(-1);
+ const steps = [];
+
+ const snapshot = () => [...dp];
+
+ // Fill dp array
+ for (let i = 0; i < n; i++) {
+ for (let j = 0; j < i; j++) {
+ if (arr[j] < arr[i] && dp[j] + 1 > dp[i]) {
+ parent[i] = j;
+ dp[i] = dp[j] + 1;
+ steps.push({
+ dp: snapshot(),
+ active: { i, j },
+ match: { i, j },
+ message: `arr[${j}] (${arr[j]}) < arr[${i}] (${arr[i]}) → dp[${i}] = dp[${j}] + 1 = ${dp[i]}`
+ });
+ } else {
+ steps.push({
+ dp: snapshot(),
+ active: { i, j },
+ message: `arr[${j}] (${arr[j]}) >= arr[${i}] (${arr[i]}) → no update, dp[${i}] remains ${dp[i]}`
+ });
+ }
+ }
+ }
+
+ // Find LIS length and reconstruct sequence
+ let lisLen = 0, lisEnd = 0;
+ for (let i = 0; i < n; i++) {
+ if (dp[i] > lisLen) {
+ lisLen = dp[i];
+ lisEnd = i;
+ }
+ }
+
+ const sequence = [];
+ let t = lisEnd;
+ while (t !== -1) {
+ sequence.push(arr[t]);
+ t = parent[t];
+ }
+ sequence.reverse();
+
+ steps.push({
+ dp: snapshot(),
+ message: `Final LIS sequence = [${sequence.join(', ')}], length = ${lisLen}`,
+ sequence,
+ });
+
+ return steps;
+}
diff --git a/src/components/dynamic-programming/LISVisualizer.jsx b/src/components/dynamic-programming/LISVisualizer.jsx
new file mode 100644
index 0000000..d0bc478
--- /dev/null
+++ b/src/components/dynamic-programming/LISVisualizer.jsx
@@ -0,0 +1,191 @@
+import React, { useState, useEffect, useRef } from "react";
+import { longestIncreasingSubsequenceSteps } from "../../algorithms/dynamic-programming/longestIncreasingSubsequence";
+
+const DPArray = ({ dp, active }) => {
+ if (!dp || dp.length === 0) return null;
+
+ return (
+
+
+ DP Array (LIS Lengths)
+
+
+ {dp.map((val, i) => {
+ const isActive = active && active.i === i;
+ const color = isActive ? "bg-blue-600" : "bg-gray-700";
+ return (
+
+ {val}
+
+ );
+ })}
+
+
+ );
+};
+
+const SPEEDS = { Slow: 1200, Medium: 600, Fast: 250 };
+
+export default function LISVisualizer() {
+ const [input, setInput] = useState("10,22,9,33,21,50,41,60");
+ const [steps, setSteps] = useState([]);
+ const [stepIndex, setStepIndex] = useState(0);
+ const [isPlaying, setIsPlaying] = useState(false);
+ const [speed, setSpeed] = useState(SPEEDS.Medium);
+ const timer = useRef(null);
+
+ const handleStart = () => {
+ const arr = input
+ .split(",")
+ .map(x => parseInt(x.trim()))
+ .filter(x => !isNaN(x));
+ const s = longestIncreasingSubsequenceSteps(arr);
+ setSteps(s);
+ setStepIndex(0);
+ setIsPlaying(false);
+ };
+
+ useEffect(() => {
+ if (isPlaying && stepIndex < steps.length - 1) {
+ timer.current = setInterval(() => {
+ setStepIndex(i => i + 1);
+ }, speed);
+ } else clearInterval(timer.current);
+
+ return () => clearInterval(timer.current);
+ }, [isPlaying, stepIndex, steps.length, speed]);
+
+ const togglePlay = () => {
+ if (stepIndex === steps.length - 1) setStepIndex(0);
+ setIsPlaying(!isPlaying);
+ };
+
+ const current = steps[stepIndex] || {};
+ const finalLIS =
+ stepIndex === steps.length - 1 ? current.sequence?.join(", ") : "";
+
+ return (
+
+
+
+ Longest Increasing Subsequence (LIS)
+
+
+
+
+ This visualizer demonstrates how the LIS DP array is updated
+ step-by-step and how the final increasing subsequence is derived.
+
+
+
+
+
+
+ setInput(e.target.value)}
+ className="w-full mt-2 p-2 rounded-lg bg-gray-700 border border-gray-600 text-white"
+ />
+
+
+
+
+
+ {steps.length > 0 ? (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Step {stepIndex + 1} / {steps.length}
+
+
+
+
+
+
+ Current Action
+
+
+ {current.message || "Processing..."}
+
+
+
+ {current.dp &&
}
+
+ {finalLIS && (
+
+
+ Final LIS ={" "}
+ {finalLIS}
+
+
+ )}
+
+ >
+ ) : (
+
+
Welcome to the LIS Visualizer!
+
Enter an array and click “Start Visualization”.
+
+ )}
+
+
+ );
+}
diff --git a/src/pages/dynamic-programming/DyanmicProgrammingPage.jsx b/src/pages/dynamic-programming/DyanmicProgrammingPage.jsx
index e306929..63f93ac 100644
--- a/src/pages/dynamic-programming/DyanmicProgrammingPage.jsx
+++ b/src/pages/dynamic-programming/DyanmicProgrammingPage.jsx
@@ -6,7 +6,9 @@ import FibonacciSequence from "./FibonacciSequence";
import Knapsack from "./Knapsack";
import PascalTriangle from "./PascalTriangle";
import LCSPage from "./LCS";
-import CoinChange from "./CoinChange"; // ✅ Added import
+import LISPage from "./LIS";
+import CoinChange from "./CoinChange";
+
import RodCutting from "./RodCutting";
export default function DynamicProgrammingPage() {
@@ -51,7 +53,13 @@ export default function DynamicProgrammingPage() {
);
- case "CoinChange": // ✅ Added new algorithm case
+ case "LongestIncreasingSubsequence":
+ return (
+
+
+
+ );
+ case "CoinChange":
return (
@@ -127,7 +135,8 @@ export default function DynamicProgrammingPage() {
- {/* ✅ Added */}
+
+
diff --git a/src/pages/dynamic-programming/LIS.jsx b/src/pages/dynamic-programming/LIS.jsx
new file mode 100644
index 0000000..d70fc74
--- /dev/null
+++ b/src/pages/dynamic-programming/LIS.jsx
@@ -0,0 +1,6 @@
+import React from "react";
+import LISVisualizer from "@/components/dynamic-programming/LISVisualizer";
+
+export default function LISPage() {
+ return ;
+}