operators, int start, int end) {
+
+ int len = end - start + 1;
+
+ for (int l = 2; l < len; ++l) {
+
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println(new DifferentWaysToAddParenthesis().diffWaysToCompute("2*3-4*5/7/12"));
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/dp/MatchsticksToSquare.java b/data-structures/src/main/java/com/thealgorithm/dp/MatchsticksToSquare.java
new file mode 100644
index 0000000..4672e3c
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/dp/MatchsticksToSquare.java
@@ -0,0 +1,102 @@
+package com.thealgorithm.dp;
+
+/**
+ * @author: Subham Santra
+ */
+public class MatchsticksToSquare {
+ static class Solution {
+ Boolean[][] DP;
+
+ int getMask(boolean a, boolean b, boolean c, boolean d) {
+ int mask = 0b0000;
+ if (a) mask |= 0b1000;
+ if (b) mask |= 0b0100;
+ if (c) mask |= 0b0010;
+ if (d) mask |= 0b0001;
+ return mask;
+ }
+
+ public boolean makesquare(int[] matchsticks) {
+ int n = matchsticks.length;
+ DP = new Boolean[n + 1][5];
+ int sum = 0;
+ for (int x : matchsticks) sum += x;
+
+ if (sum % 4 == 0) {
+ // return func(matchsticks, 0, 0, 0, 0, 0, (sum / 4));
+ return funcWithoutDP(matchsticks, 0, 0, 0, 0, 0, (sum / 4));
+ }
+ return false;
+ }
+
+ boolean funcWithoutDP(int[] arr, int index, int s1, int s2, int s3, int s4, int t) {
+ if (index == arr.length) {
+ if (s1 == s2 && s2 == s3 && s3 == s4 && s4 == t) {
+ return true;
+ }
+ return false;
+ }
+
+ return func(arr, index + 1, s1 + arr[index], s2, s3, s4, t)
+ || func(arr, index + 1, s1, s2 + arr[index], s3, s4, t)
+ || func(arr, index + 1, s1, s2, s3 + arr[index], s4, t)
+ || func(arr, index + 1, s1, s2, s3, s4 + arr[index], t);
+ }
+
+ boolean func(int[] arr, int index, int s1, int s2, int s3, int s4, int t) {
+ if (index == arr.length) {
+ if (s1 == s2 && s2 == s3 && s3 == s4 && s4 == t) {
+ return true;
+ }
+ return false;
+ }
+
+ if (DP[index][4] != null
+ && DP[index][1] != null
+ && DP[index][2] != null
+ && DP[index][3] != null) {
+ return DP[index][4] || DP[index][1] || DP[index][2] || DP[index][3];
+ }
+
+ DP[index][1] = func(arr, index + 1, s1 + arr[index], s2, s3, s4, t);
+ DP[index][2] = func(arr, index + 1, s1, s2 + arr[index], s3, s4, t);
+ DP[index][3] = func(arr, index + 1, s1, s2, s3 + arr[index], s4, t);
+ DP[index][4] = func(arr, index + 1, s1, s2, s3, s4 + arr[index], t);
+
+ return DP[index][1] || DP[index][2] || DP[index][3] || DP[index][4];
+ }
+ }
+
+ /**
+ * 1 1 2 2 2
+ *
+ * -> 8 / 4 == 2
+ *
+ *
1 1 2 2 2
+ *
+ *
{1, 1} {2} {2} {2}
+ *
+ *
size = 5
+ *
+ *
{1, 1, 1, 2, 3, 3, 4, 5} {3, 2} {4, 1} {5} {3, 1, 1}
+ *
+ *
0000 --> 1111 0 to 31 {1, 4, 3, 3, 4, 5}
+ *
+ *
1. Subset SUM
+ *
+ *
[] [] [] []
+ *
+ *
--> bit DP --> 0000 -> int[index][mask] boolean [][][][][]DP
+ *
+ *
f (s1, s2, s3, s4, i, T) { // O(4^N) if (s1 == s2 == s3 == s4 == t) --> true; if i >= length
+ * --> false; if any of (s1, s2, s3, s4) > T --> false
+ *
+ *
return f(s1 + a[i], s2, s3, s4, i + 1, T) OR f(s1, s2 + a[i], s3, s4, i + 1, T) OR f(s1, s2,
+ * s3 + a[i], s4, i + 1, T) OR f(s1, s2, s3, s4 + a[i], i + 1, T) }
+ */
+ public static void main(String[] args) {
+ System.out.println(new Solution().makesquare(new int[] {1, 1, 2, 2, 2}));
+ System.out.println(new Solution().makesquare(new int[] {3, 3, 3, 3, 4}));
+ System.out.println(new Solution().makesquare(new int[] {5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3}));
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/dp/StrangePrinter.java b/data-structures/src/main/java/com/thealgorithm/dp/StrangePrinter.java
new file mode 100644
index 0000000..f67ce13
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/dp/StrangePrinter.java
@@ -0,0 +1,50 @@
+package com.thealgorithm.dp;
+
+/**
+ * @author: Subham Santra
+ */
+public class StrangePrinter {
+ static class Solution {
+ public int strangePrinter(String s) {
+ return strangePrinter(s, 0, s.length() - 1);
+ }
+
+ int strangePrinter(String s, int lo, int hi) {
+ if (lo < 0 || lo >= s.length() || hi < 0 || hi >= s.length()) {
+ return 0;
+ }
+ if (lo > hi) {
+ return 0;
+ }
+
+ System.out.println(s.substring(lo, hi + 1));
+
+ boolean allSame = true;
+ for (int i = lo; i <= hi; ++i) {
+ if (s.charAt(i) != s.charAt(lo)) {
+ allSame = false;
+ }
+ }
+
+ if (allSame) {
+ return 1;
+ }
+ int ans = 10000;
+
+ for (int i = lo, j = hi; i <= j; ++i, --j) {
+ if (s.charAt(i) != s.charAt(j)) {
+ int v =
+ strangePrinter(s, lo, i) + strangePrinter(s, i + 1, j) + strangePrinter(s, j + 1, hi);
+ ans = Math.min(ans, v);
+ break;
+ }
+ }
+
+ return ans;
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println(new Solution().strangePrinter("abcabccb"));
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/graph/Capacity.java b/data-structures/src/main/java/com/thealgorithm/graph/Capacity.java
new file mode 100644
index 0000000..dfdfa15
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/graph/Capacity.java
@@ -0,0 +1,6 @@
+package com.thealgorithm.graph;
+
+/**
+ * @author: Subham Santra
+ */
+public class Capacity {}
diff --git a/data-structures/src/main/java/com/thealgorithm/graph/Edge.java b/data-structures/src/main/java/com/thealgorithm/graph/Edge.java
index d0bf120..e2588bd 100644
--- a/data-structures/src/main/java/com/thealgorithm/graph/Edge.java
+++ b/data-structures/src/main/java/com/thealgorithm/graph/Edge.java
@@ -11,13 +11,50 @@ public class Edge {
private Vertex vertex1;
private Vertex vertex2;
private double weight = 1D;
+ private final int capacity;
+ private int currentFlow;
+ private int residualCapacity;
public static Edge createSimpleEdgeUnWeighted(V v1, V v2) {
- return new Edge<>(Vertex.create(v1), Vertex.create(v2), 0D);
+ return new Edge<>(Vertex.create(v1), Vertex.create(v2), 0D, 0, 0, 0);
}
public static Edge createEdge(V v1, V v2, double weight) {
- return new Edge<>(Vertex.create(v1), Vertex.create(v2), weight);
+ return new Edge<>(Vertex.create(v1), Vertex.create(v2), weight, 0, 0, 0);
+ }
+
+ public static Edge createNetworkEdge(V v1, V v2, int capacity) {
+ return new Edge<>(Vertex.create(v1), Vertex.create(v2), 0D, capacity, 0, capacity);
+ }
+
+ public int reduceFlow(int delta) {
+ if (currentFlow - delta < 0) {
+ throw new RuntimeException("Flow can not be (-)ve");
+ }
+ currentFlow -= delta;
+ residualCapacity += delta;
+ return residualCapacity;
+ }
+
+ public int increaseFlow(int delta) {
+ if (currentFlow + delta > capacity) {
+ throw new RuntimeException("Flow can not be more than capacity");
+ }
+ currentFlow += delta;
+ residualCapacity -= delta;
+ return residualCapacity;
+ }
+
+ public int setFlow(int flow) {
+ if (flow < 0) {
+ throw new RuntimeException("Flow can not be (-)ve");
+ }
+ if (flow > capacity) {
+ throw new RuntimeException("Flow can not be more than capacity");
+ }
+ currentFlow = flow;
+ residualCapacity = capacity - flow;
+ return residualCapacity;
}
@Override
diff --git a/data-structures/src/main/java/com/thealgorithm/graph/EdmondKarpAlgorithm.java b/data-structures/src/main/java/com/thealgorithm/graph/EdmondKarpAlgorithm.java
new file mode 100644
index 0000000..139ac9e
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/graph/EdmondKarpAlgorithm.java
@@ -0,0 +1,97 @@
+package com.thealgorithm.graph;
+
+import com.thealgorithm.commons.Pair;
+import java.util.ArrayDeque;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Queue;
+
+/**
+ * @author: Subham Santra
+ */
+public class EdmondKarpAlgorithm {
+ private static final int INF = Integer.MAX_VALUE;
+
+ private int BFS(
+ final Vertex source,
+ final Vertex sink,
+ final Map, Vertex> parent,
+ final Map, Map, Integer>> capacityMatrix) {
+
+ Queue, Integer>> queue = new ArrayDeque<>();
+ queue.add(Pair.of(source, INF));
+
+ while (!queue.isEmpty()) {
+ Pair, Integer> vPair = queue.poll();
+ Vertex currentVertex = vPair.getFirst();
+ for (Vertex neighbor : currentVertex.getNeighbors()) {
+ if ((parent.get(neighbor) == null)
+ && (capacityMatrix.get(currentVertex).get(neighbor) > 0)) {
+ parent.put(neighbor, currentVertex);
+ int maxFlow =
+ Math.min(capacityMatrix.get(currentVertex).get(neighbor), vPair.getSecond());
+ if (currentVertex.equals(sink)) {
+ return maxFlow;
+ }
+ queue.add(Pair.of(neighbor, maxFlow));
+ }
+ }
+ }
+ return 0;
+ }
+
+ public int maxFlow(
+ final Graph graph, final Vertex source, final Vertex sink) {
+ Map, Map, Integer>> capacityMatrix = new HashMap<>();
+
+ for (var v : graph.getVertexSet()) {
+ capacityMatrix.put(v, new HashMap<>());
+ }
+ for (var e : capacityMatrix.keySet()) {
+ for (var v : graph.getVertexSet()) {
+ capacityMatrix.get(e).put(v, 0);
+ }
+ }
+ for (var edge : graph.getEdgeSet()) {
+ capacityMatrix.get(edge.getVertex1()).put(edge.getVertex2(), edge.getResidualCapacity());
+ }
+
+ int totalFlow = 0;
+
+ while (true) {
+ Map, Vertex> parent = new HashMap<>();
+ int maxFlow = BFS(source, sink, parent, capacityMatrix);
+ if (maxFlow == 0) {
+ break;
+ }
+ totalFlow += maxFlow;
+ Vertex v = sink;
+ while (!v.equals(source)) {
+ Vertex p = parent.get(v);
+ capacityMatrix.get(p).put(v, capacityMatrix.get(p).get(v) - maxFlow);
+ capacityMatrix.get(v).put(p, capacityMatrix.get(v).get(p) + maxFlow);
+ v = p;
+ }
+ }
+ return totalFlow;
+ }
+
+ public static void main(String[] args) {
+ // Finding MAX FLOW from source to destination
+ Graph graph = new Graph<>(true);
+
+ graph.addEdge(Edge.createNetworkEdge('S', 'A', 7));
+ graph.addEdge(Edge.createNetworkEdge('S', 'D', 4));
+ graph.addEdge(Edge.createNetworkEdge('D', 'A', 3));
+ graph.addEdge(Edge.createNetworkEdge('D', 'A', 3));
+ graph.addEdge(Edge.createNetworkEdge('D', 'C', 2));
+ graph.addEdge(Edge.createNetworkEdge('A', 'C', 3));
+ graph.addEdge(Edge.createNetworkEdge('A', 'B', 5));
+ graph.addEdge(Edge.createNetworkEdge('B', 'T', 8));
+ graph.addEdge(Edge.createNetworkEdge('C', 'B', 3));
+ graph.addEdge(Edge.createNetworkEdge('C', 'T', 5));
+
+ System.out.println(
+ new EdmondKarpAlgorithm().maxFlow(graph, graph.getVertex('S'), graph.getVertex('T')));
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/graph/EulerianPathOnDirectedGraph.java b/data-structures/src/main/java/com/thealgorithm/graph/EulerianPathOnDirectedGraph.java
new file mode 100644
index 0000000..0fbc731
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/graph/EulerianPathOnDirectedGraph.java
@@ -0,0 +1,44 @@
+//package com.thealgorithm.graph;
+//
+//import java.util.HashMap;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.Set;
+//
+///**
+// * @author: Subham Santra
+// */
+//public class EulerianPathOnDirectedGraph {
+//
+// public static List> findEulerianPath(Graph graph) {
+// Set> edgeSet = graph.getEdgeSet();
+// Set> vertexSet = graph.getVertexSet();
+// Map, int[]> degree = new HashMap<>(); // {int, out}
+//
+// for (var vrtx : vertexSet) {
+// degree.put(vrtx, new int[] {0, 0});
+// }
+//
+// for (var edge : edgeSet) {
+// degree.get(edge.getVertex2())[0]++;
+// degree.get(edge.getVertex1())[1]++;
+// }
+//
+// // Find a vertex where, out > in
+// Vertex v = null;
+// for (var vrtx: vertexSet) {
+// if (degree.get(vrtx)[1] > degree.get(vrtx)[0]) {
+// v = vrtx;
+// break;
+// }
+// }
+//
+// while (true) {
+// Set> neighbors = v.getNeighbors();
+//
+// Math.g
+// }
+// }
+//
+// public static void main(String[] args) {}
+//}
diff --git a/data-structures/src/main/java/com/thealgorithm/graph/Graph.java b/data-structures/src/main/java/com/thealgorithm/graph/Graph.java
index abad3c4..839243c 100644
--- a/data-structures/src/main/java/com/thealgorithm/graph/Graph.java
+++ b/data-structures/src/main/java/com/thealgorithm/graph/Graph.java
@@ -38,4 +38,8 @@ void clear() {
edgeSet.clear();
isDirected = false;
}
+
+ Vertex getVertex(K key) {
+ return vertexSet.stream().filter(v -> v.getKey().equals(key)).findFirst().get();
+ }
}
diff --git a/data-structures/src/main/java/com/thealgorithm/graph/RegionCutBySlashes.java b/data-structures/src/main/java/com/thealgorithm/graph/RegionCutBySlashes.java
new file mode 100644
index 0000000..4caf7cd
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/graph/RegionCutBySlashes.java
@@ -0,0 +1,135 @@
+package com.thealgorithm.graph;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @author: Subham Santra
+ * @implNote : For in depth understanding check this leetcode
+ * post
+ */
+public class RegionCutBySlashes {
+
+ public static void main(String[] args) {
+ System.out.println(new RegionCutBySlashes().regionsBySlashes(new String[] {" /", "/ "}));
+ System.out.println(new RegionCutBySlashes().regionsBySlashes(new String[] {" /", " "}));
+ System.out.println(new RegionCutBySlashes().regionsBySlashes(new String[] {"/\\", "\\/"}));
+ }
+
+ public int regionsBySlashes(String[] grid) {
+ List edges = new ArrayList<>();
+ int m = grid.length + 1;
+ int n = grid[0].toCharArray().length + 1;
+
+ for (int i = 0; i < grid.length; ++i) {
+ char[] row = grid[i].toCharArray();
+ // System.out.println(Arrays.toString(row));
+ for (int j = 0; j < row.length; ++j) {
+ if (row[j] == ' ') continue;
+ if (row[j] == '/') {
+ int u = vertexCode(i + 1, j, n);
+ int v = vertexCode(i, j + 1, n);
+ edges.add(new Edge(u, v));
+ } else if (row[j] == '\\') {
+ int u = vertexCode(i, j, n);
+ int v = vertexCode(i + 1, j + 1, n);
+ edges.add(new Edge(u, v));
+ }
+ }
+ }
+
+ for (int j = 0; j < n - 1; ++j) {
+ int u = vertexCode(0, j, n);
+ int v = vertexCode(0, j + 1, n);
+ edges.add(new Edge(u, v));
+ }
+
+ for (int j = 0; j < n - 1; ++j) {
+ int u = vertexCode(m - 1, j, n);
+ int v = vertexCode(m - 1, j + 1, n);
+ edges.add(new Edge(u, v));
+ }
+
+ for (int i = 0; i < m - 1; ++i) {
+ int u = vertexCode(i, 0, n);
+ int v = vertexCode(i + 1, 0, n);
+ edges.add(new Edge(u, v));
+ }
+
+ for (int i = 0; i < m - 1; ++i) {
+ int u = vertexCode(i, n - 1, n);
+ int v = vertexCode(i + 1, n - 1, n);
+ edges.add(new Edge(u, v));
+ }
+
+ // RUN U-F here
+ int cycleCount = 0;
+ UnionFind unionFind = new UnionFind((m + 1) * (n + 1) + 1);
+
+ for (Edge edge : edges) {
+ if (unionFind.addEdge(edge)) {
+ cycleCount++;
+ }
+ }
+
+ return cycleCount;
+ }
+
+ int vertexCode(int i, int j, int C) {
+ return (i * C) + j + 1;
+ }
+
+ static class UnionFind {
+ private int[] UF;
+
+ public UnionFind(int size) {
+ UF = new int[size];
+ Arrays.fill(UF, -1);
+ }
+
+ boolean addEdge(Edge e) {
+ int up = parent(e.u);
+ int vp = parent(e.v);
+ if (up == vp) {
+ // If already part of same group then cycle exists;
+ return true;
+ }
+ join(up, vp);
+ return false;
+ }
+
+ int parent(int n) {
+ if (UF[n] < 0) {
+ return n;
+ }
+ return parent(UF[n]);
+ }
+
+ void join(int a, int b) {
+ int x = UF[b];
+ UF[b] = a;
+ UF[a] = UF[a] - Math.abs(x);
+ }
+ }
+
+ static class Edge {
+ int u;
+ int v;
+
+ public Edge(int u, int v) {
+ this.u = u;
+ this.v = v;
+ }
+
+ public int hashCode() {
+ return Objects.hash(u, v);
+ }
+
+ public boolean equals(Object e) {
+ return (e != null) && (e instanceof Edge) && (((Edge) e).u == u && ((Edge) e).v == v);
+ }
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/graph/ValidArrangementOfPairs.java b/data-structures/src/main/java/com/thealgorithm/graph/ValidArrangementOfPairs.java
new file mode 100644
index 0000000..955e610
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/graph/ValidArrangementOfPairs.java
@@ -0,0 +1,13 @@
+package com.thealgorithm.graph;
+
+/**
+ * @author: Subham Santra
+ */
+public class ValidArrangementOfPairs {
+
+
+
+ public static void main(String[] args){
+
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/interval/MergeInterval.java b/data-structures/src/main/java/com/thealgorithm/interval/MergeInterval.java
new file mode 100644
index 0000000..ffc98cf
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/interval/MergeInterval.java
@@ -0,0 +1,88 @@
+package com.thealgorithm.interval;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author: Subham Santra
+ */
+public class MergeInterval {
+ private List sortedInterval;
+
+ public MergeInterval() {
+ this.sortedInterval = new LinkedList<>();
+ }
+
+ List getIntervals() {
+ return sortedInterval;
+ }
+
+ void merge(int[] interval) {
+ if (sortedInterval.isEmpty()) {
+ sortedInterval.add(interval);
+ } else {
+ int position =
+ Collections.binarySearch(
+ sortedInterval,
+ interval,
+ (i1, i2) -> {
+ if (i1[0] == i2[0]) {
+ return i2[1] - i1[1];
+ }
+ return i1[0] - i2[0];
+ });
+
+ if (position < 0) {
+ position = -(position + 1);
+
+ if (sortedInterval.isEmpty()) {
+ sortedInterval.add(interval);
+ } else {
+ sortedInterval.add(position, interval);
+ int left = interval[0];
+ int right = interval[1];
+ int li = position;
+ int ri = position;
+ for (int i = position - 1; i >= 0; --i) {
+ if (inSameRange(sortedInterval.get(i), interval)) {
+ li = i;
+ left = Math.min(left, sortedInterval.get(i)[0]);
+ right = Math.max(right, sortedInterval.get(i)[1]);
+ }
+ }
+ for (int i = position; i < sortedInterval.size(); ++i) {
+ if (inSameRange(sortedInterval.get(i), interval)) {
+ ri = i;
+ right = Math.max(right, sortedInterval.get(i)[1]);
+ left = Math.min(left, sortedInterval.get(i)[0]);
+ }
+ }
+ sortedInterval.subList(li, ri + 1).clear();
+ sortedInterval.add(li, new int[] {left, right});
+ }
+ }
+ }
+ }
+
+ private boolean inSameRange(int[] interval, int[] target) {
+ return (interval[0] <= target[0] && target[1] <= interval[1])
+ || (interval[0] >= target[0] && target[1] >= interval[1]);
+ }
+
+ void print() {
+ sortedInterval.stream().forEach(a -> System.out.printf("(%d, %d)\n", a[0], a[1]));
+ System.out.println("----");
+ }
+
+ public static void main(String[] args) {
+ MergeInterval mergeInterval = new MergeInterval();
+ mergeInterval.print();
+
+ mergeInterval.merge(new int[] {1, 10});
+ mergeInterval.print();
+
+ mergeInterval.merge(new int[] {4, 8});
+ mergeInterval.print();
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/lld/DatabaseLocks.java b/data-structures/src/main/java/com/thealgorithm/lld/DatabaseLocks.java
index 9e7f921..06471a6 100644
--- a/data-structures/src/main/java/com/thealgorithm/lld/DatabaseLocks.java
+++ b/data-structures/src/main/java/com/thealgorithm/lld/DatabaseLocks.java
@@ -1,5 +1,8 @@
package com.thealgorithm.lld;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
class Service {
public void doSomething(String key) {
// read the data using key
@@ -8,5 +11,33 @@ public void doSomething(String key) {
}
public class DatabaseLocks {
- public static void main(String[] args) {}
+ private CompletableFuture doSomething() {
+ return CompletableFuture.supplyAsync(
+ () -> {
+ try {
+ Thread.sleep(1000);
+ return "Shubham";
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
+ public static void main(String[] args) throws ExecutionException, InterruptedException {
+ DatabaseLocks databaseLocks = new DatabaseLocks();
+
+ databaseLocks
+ .doSomething()
+ .thenAcceptAsync(
+ (aString) -> {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ System.out.println(aString);
+ });
+
+ Thread.sleep(10000);
+ }
}
diff --git a/data-structures/src/main/java/com/thealgorithm/lld/SnapshotArray.java b/data-structures/src/main/java/com/thealgorithm/lld/SnapshotArray.java
new file mode 100644
index 0000000..56e4cd9
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/lld/SnapshotArray.java
@@ -0,0 +1,79 @@
+package com.thealgorithm.lld;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NavigableSet;
+import java.util.TreeSet;
+
+/**
+ * @author: Subham Santra
+ */
+public class SnapshotArray {
+ static class Pair {
+ int snap;
+ int val;
+
+ public Pair(int s, int v) {
+ this.snap = s;
+ this.val = v;
+ }
+
+ public String toString() {
+ return String.format("[%d @%d]", val, snap);
+ }
+ }
+
+ private int snapId;
+ private final Map> snapshots;
+
+ public SnapshotArray(int length) {
+ snapshots = new HashMap<>();
+ for (int i = 0; i < length; ++i) {
+ snapshots.put(i, new TreeSet<>(Comparator.comparingInt(p -> p.snap)));
+ }
+ }
+
+ public void set(int index, int val) {
+ TreeSet change = snapshots.get(index);
+ if (!change.isEmpty() && change.getLast().snap == snapId) {
+ change.getLast().val = val;
+ } else {
+ change.add(new Pair(snapId, val));
+ }
+ print();
+ }
+
+ public int snap() {
+ return snapId++;
+ }
+
+ public int get(int index, int snap_id) {
+ TreeSet change = snapshots.get(index);
+ NavigableSet pairs = change.headSet(new Pair(snap_id, 0), true);
+ if (pairs.isEmpty()) return 0;
+ return pairs.getLast().val;
+ }
+
+ public void print() {
+ System.out.println(snapshots);
+ }
+
+ /**
+ * Your SnapshotArray object will be instantiated and called as such: SnapshotArray obj = new
+ * SnapshotArray(length); obj.set(index,val); int param_2 = obj.snap(); int param_3 =
+ * obj.get(index,snap_id);
+ */
+ public static void main(String[] args) {
+ SnapshotArray snapshotArray = new SnapshotArray(1);
+
+ snapshotArray.set(0, 15);
+ System.out.println(snapshotArray.snap());
+ System.out.println(snapshotArray.snap());
+ System.out.println(snapshotArray.snap());
+ System.out.println(snapshotArray.get(0, 2));
+ System.out.println(snapshotArray.snap());
+ System.out.println(snapshotArray.snap());
+ System.out.println(snapshotArray.get(0, 0));
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/lld/Twitter.java b/data-structures/src/main/java/com/thealgorithm/lld/Twitter.java
new file mode 100644
index 0000000..7193b34
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/lld/Twitter.java
@@ -0,0 +1,120 @@
+package com.thealgorithm.lld;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.PriorityQueue;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+/**
+ * @author: Subham Santra
+ */
+class Tweet {
+ int tweetId;
+ int time;
+
+ public Tweet(int te, int tm) {
+ this.tweetId = te;
+ this.time = tm;
+ }
+
+ public int hashcode() {
+ return time;
+ }
+
+ public boolean equals(Tweet t) {
+ if (t == null) return false;
+ return t.time == time;
+ }
+
+ @Override
+ public String toString() {
+ return "Tweet{" + "tweetId=" + tweetId + ", time=" + time + '}';
+ }
+}
+
+public class Twitter {
+ private final Map> following;
+ private final Map> tweets;
+ private final AtomicInteger atom = new AtomicInteger(0);
+
+ public Twitter() {
+ following = new HashMap<>();
+ tweets = new HashMap<>();
+ }
+
+ public void postTweet(int userId, int tweetId) {
+ tweets.putIfAbsent(userId, new LinkedHashSet<>());
+ tweets.get(userId).add(new Tweet(tweetId, atom.incrementAndGet()));
+ if (tweets.get(userId).size() > 10) {
+ tweets.get(userId).removeFirst();
+ }
+ }
+
+ public List getNewsFeed(int userId) {
+ // System.out.println(following);
+ // System.out.println(tweets);
+ PriorityQueue userFeed = new PriorityQueue<>(Comparator.comparingInt(t -> t.time));
+
+ // add own tweets.
+ addToFeed(userId, userFeed, 10);
+ following.getOrDefault(userId, Set.of()).forEach(f -> addToFeed(f, userFeed, 10));
+
+ // prepare sorted result for feed
+ List resultant = new ArrayList<>();
+ resultant.addAll(userFeed);
+// Collections.sort(resultant, (t1, t2) -> t2.time - t1.time);
+ return resultant.stream().map(tweet -> tweet.tweetId).collect(Collectors.toList());
+ }
+
+ public void addToFeed(int userId, PriorityQueue feed, final int k) {
+ LinkedHashSet allTweets = tweets.get(userId);
+
+ if (allTweets == null || allTweets.isEmpty()) return;
+
+ Iterator tweetIterator = allTweets.reversed().iterator();
+ int cap = k;
+ while (tweetIterator.hasNext() && (cap > 0)) {
+ feed.add(tweetIterator.next());
+ while (feed.size() > k) {
+ feed.poll();
+ }
+ --cap;
+ }
+ }
+
+ public void follow(int followerId, int followeeId) {
+ following.putIfAbsent(followerId, new HashSet<>());
+ following.get(followerId).add(followeeId);
+ }
+
+ public void unfollow(int followerId, int followeeId) {
+ if (following.get(followerId) == null) return;
+ following.get(followerId).remove(followeeId);
+ }
+
+ public static void main(String[] args) {
+ Twitter twitter = new Twitter();
+
+ twitter.postTweet(1, 1);
+ twitter.postTweet(1, 2);
+ twitter.postTweet(1, 3);
+ twitter.postTweet(1, 4);
+ twitter.postTweet(1, 5);
+ twitter.postTweet(1, 6);
+ twitter.postTweet(1, 7);
+ twitter.postTweet(1, 8);
+ twitter.postTweet(1, 9);
+ twitter.postTweet(1, 10);
+ twitter.postTweet(1, 11);
+ System.out.println(twitter.getNewsFeed(1));
+ System.out.println(twitter.getNewsFeed(4));
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/lld/caching/AbstractCache.java b/data-structures/src/main/java/com/thealgorithm/lld/caching/AbstractCache.java
new file mode 100644
index 0000000..17c1b6b
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/lld/caching/AbstractCache.java
@@ -0,0 +1,11 @@
+package com.thealgorithm.lld.caching;
+
+/**
+ * @author: Subham Santra
+ */
+public abstract class AbstractCache implements ICache {
+ @Override
+ public long timeToLive() {
+ return 10 * 1000L;
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/lld/caching/CacheEntry.java b/data-structures/src/main/java/com/thealgorithm/lld/caching/CacheEntry.java
new file mode 100644
index 0000000..6f145de
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/lld/caching/CacheEntry.java
@@ -0,0 +1,19 @@
+package com.thealgorithm.lld.caching;
+
+import java.sql.Timestamp;
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+
+/**
+ * @author: Subham Santra
+ */
+@Getter
+@AllArgsConstructor
+@EqualsAndHashCode(onlyExplicitlyIncluded = true)
+public class CacheEntry {
+ @EqualsAndHashCode.Include
+ private K key;
+ private V val;
+ private Timestamp timestamp;
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/lld/caching/ICache.java b/data-structures/src/main/java/com/thealgorithm/lld/caching/ICache.java
new file mode 100644
index 0000000..f5f9eb8
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/lld/caching/ICache.java
@@ -0,0 +1,9 @@
+package com.thealgorithm.lld.caching;
+
+import java.util.concurrent.CompletableFuture;
+
+public interface ICache extends ICacheEvictionPolicy {
+ V fetch(K key);
+
+ CompletableFuture put(K key, V val);
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/lld/caching/ICacheEvictionPolicy.java b/data-structures/src/main/java/com/thealgorithm/lld/caching/ICacheEvictionPolicy.java
new file mode 100644
index 0000000..df6cd8b
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/lld/caching/ICacheEvictionPolicy.java
@@ -0,0 +1,13 @@
+package com.thealgorithm.lld.caching;
+
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * @author: Subham Santra
+ */
+public interface ICacheEvictionPolicy {
+ CompletableFuture evict();
+
+ long timeToLive();
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/lld/caching/LeastRecentlyUsedCache.java b/data-structures/src/main/java/com/thealgorithm/lld/caching/LeastRecentlyUsedCache.java
new file mode 100644
index 0000000..17be6c3
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/lld/caching/LeastRecentlyUsedCache.java
@@ -0,0 +1,37 @@
+package com.thealgorithm.lld.caching;
+
+import java.sql.Timestamp;
+import java.time.Instant;
+import java.util.LinkedHashMap;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * @author: Subham Santra
+ */
+public class LeastRecentlyUsedCache extends AbstractCache {
+ private LinkedHashMap> linkedHashMap = new LinkedHashMap<>();
+ private Thread sweeperThread;
+
+ public LeastRecentlyUsedCache() {
+ sweeperThread = new Thread(() -> {});
+ }
+
+ @Override
+ public V fetch(K key) {
+ return null;
+ }
+
+ @Override
+ public CompletableFuture put(K key, V val) {
+ return CompletableFuture.runAsync(
+ () -> {
+ linkedHashMap.remove(key);
+ linkedHashMap.putLast(key, new CacheEntry<>(key, val, Timestamp.from(Instant.now())));
+ });
+ }
+
+ @Override
+ public CompletableFuture evict() {
+ return CompletableFuture.runAsync(() -> {});
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/miscelleneous/TimeTakenToCrossTheDoor.java b/data-structures/src/main/java/com/thealgorithm/miscelleneous/TimeTakenToCrossTheDoor.java
new file mode 100644
index 0000000..43be605
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/miscelleneous/TimeTakenToCrossTheDoor.java
@@ -0,0 +1,97 @@
+package com.thealgorithm.miscelleneous;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.PriorityQueue;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author: Subham Santra
+ */
+public class TimeTakenToCrossTheDoor {
+ static class Node implements Comparable {
+ int index;
+ int state;
+ int time;
+
+ public Node(int index, int state, int time) {
+ this.index = index;
+ this.state = state;
+ this.time = time;
+ }
+
+ @Override
+ public int compareTo(Node o) {
+ if (time == o.time) {
+ return Integer.compare(index, o.index);
+ }
+ return Integer.compare(time, o.time);
+ }
+ }
+
+ List sameArrivals(PriorityQueue priorityQueue) {
+ List nodes = new ArrayList<>();
+ int nextTime = priorityQueue.isEmpty() ? 0 : priorityQueue.peek().time;
+ while (!priorityQueue.isEmpty() && priorityQueue.peek().time == nextTime) {
+ nodes.add(priorityQueue.poll());
+ }
+ return nodes;
+ }
+
+ public int[] solve(int[] arrival, int[] state) {
+ final PriorityQueue entryQueue = new PriorityQueue<>();
+ final int n = arrival.length;
+ final int[] timeToCross = new int[n];
+
+ for (int i = 0; i < n; ++i) {
+ entryQueue.add(new Node(i, state[i], arrival[i]));
+ }
+
+ AtomicInteger lastSecond = new AtomicInteger(-2);
+ AtomicInteger lastState = new AtomicInteger(-2);
+ while (!entryQueue.isEmpty()) {
+ List sameArrivals = sameArrivals(entryQueue);
+ Node possibleNext;
+ if (lastSecond.get() == sameArrivals.get(0).time - 1) {
+ // Last second is used by someone else.
+ possibleNext =
+ sameArrivals.stream()
+ .filter(node -> node.state == lastState.get())
+ .findFirst()
+ .orElse(sameArrivals.get(0));
+ } else {
+ possibleNext = sameArrivals.get(0);
+ }
+
+ // update result array for possibleNext
+ timeToCross[possibleNext.index] = possibleNext.time;
+ lastState.set(possibleNext.state);
+ lastSecond.set(possibleNext.time);
+
+ // add again to entry queue
+ sameArrivals.stream()
+ .filter(node -> node.index != possibleNext.index)
+ .peek(node -> node.time++)
+ .forEach(entryQueue::add);
+ }
+
+ return timeToCross;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(
+ Arrays.toString(
+ new TimeTakenToCrossTheDoor()
+ .solve(new int[] {0, 1, 1, 2, 4}, new int[] {0, 1, 0, 0, 1})));
+
+ System.out.println(
+ Arrays.toString(
+ new TimeTakenToCrossTheDoor()
+ .solve(new int[] {0, 0, 1, 1, 1, 2, 3}, new int[] {0, 1, 0})));
+
+ System.out.println(
+ Arrays.toString(
+ new TimeTakenToCrossTheDoor().solve(new int[] {0, 0, 0}, new int[] {1, 0, 1})));
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/strings/BasicCalculator.java b/data-structures/src/main/java/com/thealgorithm/strings/BasicCalculator.java
new file mode 100644
index 0000000..07236e8
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/strings/BasicCalculator.java
@@ -0,0 +1,94 @@
+package com.thealgorithm.strings;
+
+import java.util.ArrayDeque;
+
+/**
+ * @author: Subham Santra
+ */
+public class BasicCalculator {
+ public int calculate(String s) {
+ s = clean(s);
+ ArrayDeque runstack = new ArrayDeque<>();
+ ArrayDeque opstack = new ArrayDeque<>();
+
+ for (int i = 0; i < s.length(); ) {
+ char c = s.charAt(i);
+ if (Character.isDigit(c)) {
+ int[] e = nextInt(s, i);
+ runstack.addLast(e[0]);
+ i = e[1];
+ while (!opstack.isEmpty()
+ && (opstack.getLast() == '*' || opstack.getLast() == '/')
+ && runstack.size() > 1) {
+ int last = runstack.pollLast();
+ int secondLast = runstack.pollLast();
+ runstack.addLast(perform(secondLast, last, opstack.pollLast()));
+ }
+ } else {
+ opstack.addLast(c);
+ ++i;
+ }
+ }
+ while (runstack.size() > 1) {
+ int last = runstack.pollFirst();
+ int secondLast = runstack.pollFirst();
+ int result = perform(last, secondLast, opstack.pollFirst());
+ runstack.addFirst(result);
+ }
+ return runstack.peek();
+ }
+
+ int ord(char c) {
+ switch (c) {
+ case '/':
+ return 4;
+ case '*':
+ return 3;
+ case '+':
+ return 1;
+ case '-':
+ return 1;
+ }
+ return 0;
+ }
+
+ private int perform(int i, int j, char op) {
+ switch (op) {
+ case '-':
+ return i - j;
+ case '+':
+ return i + j;
+ case '*':
+ return i * j;
+ case '/':
+ return i / j;
+ }
+ return 0;
+ }
+
+ String clean(String s) {
+ StringBuilder sb = new StringBuilder();
+ for (char c : s.toCharArray()) {
+ if (c != ' ') sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ int[] nextInt(String s, int i) {
+ int n = 0;
+ while (i < s.length() && Character.isDigit(s.charAt(i))) {
+ n = (n * 10) + (s.charAt(i) - '0');
+ ++i;
+ }
+ return new int[] {n, i};
+ }
+
+ public static void main(String[] args) {
+ System.out.println(new BasicCalculator().calculate("1-1"));
+ System.out.println(new BasicCalculator().calculate("1-1+1"));
+ System.out.println(new BasicCalculator().calculate("2+3*4/2-1"));
+ System.out.println(new BasicCalculator().calculate(" 3+5 / 2 "));
+ // [8,1
+ // [-
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/strings/ReorganizeStrings.java b/data-structures/src/main/java/com/thealgorithm/strings/ReorganizeStrings.java
new file mode 100644
index 0000000..41bcf6c
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/strings/ReorganizeStrings.java
@@ -0,0 +1,73 @@
+package com.thealgorithm.strings;
+
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.PriorityQueue;
+import java.util.stream.Collectors;
+
+/**
+ * @author: Subham Santra
+ */
+public class ReorganizeStrings {
+ static class Solution {
+ static class Entry {
+ char c;
+ int count;
+
+ public Entry(char c, int count) {
+ this.c = c;
+ this.count = count;
+ }
+ }
+
+ public String reorganizeString(String s) {
+ Comparator comp = (e1, e2) -> Integer.compare(e2.count, e1.count);
+ PriorityQueue priorityQueue = new PriorityQueue<>(comp);
+ Map frequency =
+ s.chars().boxed().collect(Collectors.toMap(c -> c, c -> 1, Integer::sum));
+ System.out.println(frequency);
+ frequency.forEach((key, value) -> priorityQueue.add(new Entry((char) key.intValue(), value)));
+
+ LinkedList list = new LinkedList<>();
+
+ ListIterator integerListIterator = list.listIterator();
+
+
+ StringBuilder b = new StringBuilder();
+
+ while (!priorityQueue.isEmpty()) {
+ Entry top = priorityQueue.poll();
+ if (b.isEmpty()) {
+ b.append(top.c);
+ top.count--;
+ if (top.count > 0) priorityQueue.add(top);
+ } else {
+ if (b.charAt(b.length() - 1) == top.c) {
+ if (priorityQueue.isEmpty()) {
+ return "";
+ }
+ Entry second = priorityQueue.poll();
+ b.append(second.c);
+ second.count--;
+ priorityQueue.add(top);
+ if (second.count > 0) priorityQueue.add(second);
+ } else {
+ b.append(top.c);
+ top.count--;
+ if (top.count > 0) priorityQueue.add(top);
+ }
+ }
+ }
+
+ return b.toString();
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println(new Solution().reorganizeString("aabbab"));
+ System.out.println(new Solution().reorganizeString("aaaabccccd"));
+ System.out.println(new Solution().reorganizeString("aaabbbccc"));
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/strings/RollingHash.java b/data-structures/src/main/java/com/thealgorithm/strings/RollingHash.java
new file mode 100644
index 0000000..de90b54
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/strings/RollingHash.java
@@ -0,0 +1,35 @@
+package com.thealgorithm.strings;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author: Subham Santra
+ */
+public class RollingHash {
+ private static final long PRIME = 67;
+ private static final long MOD = (long) (1e9 + 7);
+
+ private long hash(char[] txt, int i, int j) {
+ long hash = 0;
+ for (int idx = i; idx <= j; ++idx) {
+ hash = (hash + ((long) ((txt[idx] - 'a') * Math.pow(PRIME, (idx - i)))) % MOD) % MOD;
+ }
+ return hash;
+ }
+
+ public List findOccurrences(char[] pattern, char[] text) {
+ List occurrences = new ArrayList<>();
+
+ int PL = pattern.length;
+ long hashOfPattern = hash(pattern, 0, PL - 1);
+
+// for (int i = 0)
+
+ return occurrences;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(new RollingHash().hash("abc".toCharArray(), 0, 2));
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/strings/StringWithoutAAAorBBB.java b/data-structures/src/main/java/com/thealgorithm/strings/StringWithoutAAAorBBB.java
new file mode 100644
index 0000000..c943b9e
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/strings/StringWithoutAAAorBBB.java
@@ -0,0 +1,49 @@
+package com.thealgorithm.strings;
+
+/**
+ * @author: Subham Santra
+ */
+public class StringWithoutAAAorBBB {
+ static class Solution {
+ public String strWithout3a3b(int a, int b) {
+ StringBuilder ans = new StringBuilder();
+ while (a > 0 || b > 0) {
+ if (ans.toString().endsWith("aa")) {
+ ans.append("b");
+ --b;
+ } else if (ans.toString().endsWith("bb")) {
+ ans.append("a");
+ --a;
+ } else {
+ if (a > b) {
+ ans.append("a");
+ --a;
+ } else {
+ ans.append("b");
+ --b;
+ }
+ }
+ }
+
+ return ans.toString();
+ }
+ }
+
+ /**
+ * 3 1 aaba
+ *
+ * if (a == b) --> ababa....
+ *
+ *
if (a == b + 1) --> abab...ba
+ *
+ *
if (a == b + 2) --> aabab...ba if (a == b + 3) --> aabaab...ba if (a == b + b + 1) -->
+ * aabaab...baa
+ *
+ *
1 2
+ *
+ *
a a b a a
+ */
+ public static void main(String[] args) {
+ System.out.println(new Solution().strWithout3a3b(6, 10));
+ }
+}
diff --git a/data-structures/src/main/java/com/thealgorithm/strings/SumOfPrefixScores.java b/data-structures/src/main/java/com/thealgorithm/strings/SumOfPrefixScores.java
new file mode 100644
index 0000000..1265644
--- /dev/null
+++ b/data-structures/src/main/java/com/thealgorithm/strings/SumOfPrefixScores.java
@@ -0,0 +1,126 @@
+//package com.thealgorithm.strings;
+//
+//import java.util.Arrays;
+//
+///**
+// * @author: Subham Santra
+// */
+//public class SumOfPrefixScores {
+// static class TrieNode {
+// char c;
+// TrieNode[] nxt;
+// boolean isEnd;
+// int score;
+//
+// public TrieNode(char c) {
+// this.c = c;
+// this.nxt = new TrieNode[26];
+// }
+//
+// @Override
+// public String toString() {
+// return "<" + c + ", " + Arrays.toString(nxt) + '>';
+// }
+// }
+//
+// static class Trie {
+// TrieNode root = new TrieNode('a');
+//
+// void add(String a) {
+// add(a, 0, root);
+// }
+//
+// void add(String a, int i, TrieNode node) {
+// if (i == a.length()) return;
+// node.score++;
+// if (node.nxt[a.charAt(i) - 'a'] != null) {
+// if (i == a.length() - 1) {
+// node.nxt[a.charAt(i) - 'a'].isEnd = true;
+// }
+// add(a, i + 1, node.nxt[a.charAt(i) - 'a']);
+// return;
+// }
+// node.nxt[a.charAt(i) - 'a'] = new TrieNode(a.charAt(i));
+// node.nxt[a.charAt(i) - 'a'].score = 1;
+// if (i == a.length() - 1) {
+// node.nxt[a.charAt(i) - 'a'].isEnd = true;
+// }
+// add(a, i + 1, node.nxt[a.charAt(i) - 'a']);
+// }
+//
+// // void DFS() {
+// // DFS(root);
+// // }
+//
+// // int DFS(TrieNode node) {
+// // if (node == null) {
+// // return 0;
+// // }
+// //
+// // boolean isNull = true;
+// // for (int i = 0; i < node.nxt.length; ++i) {
+// // if (node.nxt[i] != null) {
+// // isNull = false;
+// // break;
+// // }
+// // }
+// //
+// // if (isNull) {
+// // return node.score = 1;
+// // }
+// //
+// // for (int i = 0; i < node.nxt.length; ++i) {
+// // node.score += DFS(node.nxt[i]);
+// // }
+// //
+// // node.score += (node.isEnd ? 1 : 0);
+// // return node.score;
+// // }
+//
+// int scoreOf(String a) {
+// TrieNode node = root.nxt[a.charAt(0) - 'a'];
+// int i = 0;
+// int score = 0;
+//
+// while (node != null) {
+// score += node.score;
+// if (i + 1 < a.length()) {
+// node = node.nxt[a.charAt(i + 1) - 'a'];
+// i++;
+// } else {
+// break;
+// }
+// }
+//
+// return score;
+// }
+// }
+//
+// static class Solution {
+// public int[] sumPrefixScores(String[] words) {
+// int[] score = new int[words.length];
+// Trie trie = new Trie();
+//
+// for (String word : words) trie.add(word);
+//
+// // trie.DFS();
+//
+// int idx = 0;
+// for (String word : words) {
+// score[idx] = trie.scoreOf(word);
+// idx++;
+// }
+//
+// return score;
+// }
+// }
+//
+// public static void main(String[] args) {
+// System.out.println(
+// Arrays.toString(new Solution().sumPrefixScores(new String[] {"abc", "ab", "bc", "b"})));
+//
+// System.out.println(Arrays.toString(new Solution().sumPrefixScores(new String[] {"abcd"})));
+//
+// Arrays.stream(new int[] {}).max().or
+// }
+//}
diff --git a/data-structures/src/main/resources/edmond_karp.png b/data-structures/src/main/resources/edmond_karp.png
new file mode 100644
index 0000000..ed909c4
Binary files /dev/null and b/data-structures/src/main/resources/edmond_karp.png differ
diff --git a/data-structures/src/main/resources/graph/sample.sql b/data-structures/src/main/resources/graph/sample.sql
new file mode 100644
index 0000000..d747db4
--- /dev/null
+++ b/data-structures/src/main/resources/graph/sample.sql
@@ -0,0 +1,12 @@
+
+
+
+EMPL
+id
+name
+salary
+location
+doj
+
+
+SELECT TOP 5 * FROM EMPL e WHERE DATEDIFF(year, e.doj, getdate()) >= 3 AND trim(e.location)=N'bangalore' ORDER BY e.salary DESC
diff --git a/low-level-design/src/main/java/com/thealgorithm/decorator/BasePizza.java b/low-level-design/src/main/java/com/thealgorithm/decorator/BasePizza.java
new file mode 100644
index 0000000..fb0d479
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/decorator/BasePizza.java
@@ -0,0 +1,8 @@
+package com.thealgorithm.decorator;
+
+/**
+ * @author: Subham Santra
+ */
+public abstract class BasePizza {
+ public abstract double cost();
+}
diff --git a/low-level-design/src/main/java/com/thealgorithm/decorator/ExtraCheese.java b/low-level-design/src/main/java/com/thealgorithm/decorator/ExtraCheese.java
new file mode 100644
index 0000000..29a06a3
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/decorator/ExtraCheese.java
@@ -0,0 +1,15 @@
+package com.thealgorithm.decorator;
+
+/**
+ * @author: Subham Santra
+ */
+public class ExtraCheese extends ToppingDecorator {
+ public ExtraCheese(BasePizza basePizza) {
+ super(basePizza);
+ }
+
+ @Override
+ public double cost() {
+ return this.basePizza.cost() + 35;
+ }
+}
diff --git a/low-level-design/src/main/java/com/thealgorithm/decorator/ExtraSauce.java b/low-level-design/src/main/java/com/thealgorithm/decorator/ExtraSauce.java
new file mode 100644
index 0000000..11c66f4
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/decorator/ExtraSauce.java
@@ -0,0 +1,15 @@
+package com.thealgorithm.decorator;
+
+/**
+ * @author: Subham Santra
+ */
+public class ExtraSauce extends ToppingDecorator {
+ public ExtraSauce(BasePizza basePizza) {
+ super(basePizza);
+ }
+
+ @Override
+ public double cost() {
+ return basePizza.cost() + 95;
+ }
+}
diff --git a/low-level-design/src/main/java/com/thealgorithm/decorator/FarmHouse.java b/low-level-design/src/main/java/com/thealgorithm/decorator/FarmHouse.java
new file mode 100644
index 0000000..de27a00
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/decorator/FarmHouse.java
@@ -0,0 +1,11 @@
+package com.thealgorithm.decorator;
+
+/**
+ * @author: Subham Santra
+ */
+public class FarmHouse extends BasePizza {
+ @Override
+ public double cost() {
+ return 110;
+ }
+}
diff --git a/low-level-design/src/main/java/com/thealgorithm/decorator/Margherita.java b/low-level-design/src/main/java/com/thealgorithm/decorator/Margherita.java
new file mode 100644
index 0000000..ff68224
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/decorator/Margherita.java
@@ -0,0 +1,11 @@
+package com.thealgorithm.decorator;
+
+/**
+ * @author: Subham Santra
+ */
+public class Margherita extends BasePizza {
+ @Override
+ public double cost() {
+ return 100;
+ }
+}
diff --git a/low-level-design/src/main/java/com/thealgorithm/decorator/Mashroom.java b/low-level-design/src/main/java/com/thealgorithm/decorator/Mashroom.java
new file mode 100644
index 0000000..6a99c8b
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/decorator/Mashroom.java
@@ -0,0 +1,15 @@
+package com.thealgorithm.decorator;
+
+/**
+ * @author: Subham Santra
+ */
+public class Mashroom extends ToppingDecorator {
+ public Mashroom(BasePizza basePizza) {
+ super(basePizza);
+ }
+
+ @Override
+ public double cost() {
+ return basePizza.cost() + 65;
+ }
+}
diff --git a/low-level-design/src/main/java/com/thealgorithm/decorator/Test.java b/low-level-design/src/main/java/com/thealgorithm/decorator/Test.java
new file mode 100644
index 0000000..26662b8
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/decorator/Test.java
@@ -0,0 +1,15 @@
+package com.thealgorithm.decorator;
+
+/**
+ * @author: Subham Santra
+ */
+public class Test {
+ public static void main(String[] args) {
+ BasePizza pizza = new Margherita();
+
+ // Adding toppings
+ BasePizza finalPizza = new ExtraSauce(new ExtraCheese(pizza));
+
+ System.out.println(finalPizza.cost());
+ }
+}
diff --git a/low-level-design/src/main/java/com/thealgorithm/decorator/ToppingDecorator.java b/low-level-design/src/main/java/com/thealgorithm/decorator/ToppingDecorator.java
new file mode 100644
index 0000000..f872662
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/decorator/ToppingDecorator.java
@@ -0,0 +1,12 @@
+package com.thealgorithm.decorator;
+
+/**
+ * @author: Subham Santra
+ */
+public abstract class ToppingDecorator extends BasePizza {
+ protected BasePizza basePizza;
+
+ public ToppingDecorator(BasePizza basePizza) {
+ this.basePizza = basePizza;
+ }
+}
diff --git a/low-level-design/src/main/java/com/thealgorithm/decorator/VegDelight.java b/low-level-design/src/main/java/com/thealgorithm/decorator/VegDelight.java
new file mode 100644
index 0000000..ecba4bf
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/decorator/VegDelight.java
@@ -0,0 +1,11 @@
+package com.thealgorithm.decorator;
+
+/**
+ * @author: Subham Santra
+ */
+public class VegDelight extends BasePizza {
+ @Override
+ public double cost() {
+ return 106;
+ }
+}
diff --git a/low-level-design/src/main/java/com/thealgorithm/observer/AbstractObservable.java b/low-level-design/src/main/java/com/thealgorithm/observer/AbstractObservable.java
new file mode 100644
index 0000000..ff641cf
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/observer/AbstractObservable.java
@@ -0,0 +1,34 @@
+package com.thealgorithm.observer;
+
+import java.util.List;
+import lombok.Getter;
+
+/**
+ * @author: Subham Santra
+ */
+public abstract class AbstractObservable {
+ private List observers;
+ @Getter private Object data;
+
+ public AbstractObservable(List observers, Object data) {
+ this.observers = observers;
+ this.data = data;
+ }
+
+ public void change(Object data) {
+ this.data = data;
+ notifyObservers();
+ }
+
+ private void notifyObservers() {
+ observers.forEach(AbstractObserver::observe);
+ }
+
+ public void addObserver(AbstractObserver observer) {
+ this.observers.add(observer);
+ }
+
+ public void removeObserver(AbstractObserver observer) {
+ this.observers.remove(observer);
+ }
+}
diff --git a/low-level-design/src/main/java/com/thealgorithm/observer/AbstractObserver.java b/low-level-design/src/main/java/com/thealgorithm/observer/AbstractObserver.java
new file mode 100644
index 0000000..76e0ed7
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/observer/AbstractObserver.java
@@ -0,0 +1,13 @@
+package com.thealgorithm.observer;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * @author: Subham Santra
+ */
+@AllArgsConstructor
+public abstract class AbstractObserver {
+ protected AbstractObservable observable;
+
+ public abstract void observe();
+}
diff --git a/low-level-design/src/main/java/com/thealgorithm/observer/example/FacebookWatcher.java b/low-level-design/src/main/java/com/thealgorithm/observer/example/FacebookWatcher.java
new file mode 100644
index 0000000..fbd3439
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/observer/example/FacebookWatcher.java
@@ -0,0 +1,17 @@
+package com.thealgorithm.observer.example;
+
+import com.thealgorithm.observer.AbstractObserver;
+
+/**
+ * @author: Subham Santra
+ */
+public class FacebookWatcher extends AbstractObserver {
+ public FacebookWatcher(WeatherUpdateChannel observable) {
+ super(observable);
+ }
+
+ @Override
+ public void observe() {
+ System.out.println("FROM FACEBOOK " + this.observable.getData());
+ }
+}
diff --git a/low-level-design/src/main/java/com/thealgorithm/observer/example/TelevisionWatcher.java b/low-level-design/src/main/java/com/thealgorithm/observer/example/TelevisionWatcher.java
new file mode 100644
index 0000000..0220393
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/observer/example/TelevisionWatcher.java
@@ -0,0 +1,17 @@
+package com.thealgorithm.observer.example;
+
+import com.thealgorithm.observer.AbstractObserver;
+
+/**
+ * @author: Subham Santra
+ */
+public class TelevisionWatcher extends AbstractObserver {
+ public TelevisionWatcher(WeatherUpdateChannel observable) {
+ super(observable);
+ }
+
+ @Override
+ public void observe() {
+ System.out.println("FROM T.V. " + this.observable.getData());
+ }
+}
diff --git a/low-level-design/src/main/java/com/thealgorithm/observer/example/Test.java b/low-level-design/src/main/java/com/thealgorithm/observer/example/Test.java
new file mode 100644
index 0000000..39dc3db
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/observer/example/Test.java
@@ -0,0 +1,27 @@
+package com.thealgorithm.observer.example;
+
+import java.util.ArrayList;
+
+/**
+ * @author: Subham Santra
+ */
+public class Test {
+ public static void main(String[] args) {
+ WeatherUpdateChannel weatherUpdateChannel = new WeatherUpdateChannel(new ArrayList<>(), null);
+
+ TelevisionWatcher televisionWatcher = new TelevisionWatcher(weatherUpdateChannel);
+ FacebookWatcher facebookWatcher = new FacebookWatcher(weatherUpdateChannel);
+
+ weatherUpdateChannel.addObserver(televisionWatcher);
+ weatherUpdateChannel.addObserver(facebookWatcher);
+
+ weatherUpdateChannel.change(new WeatherUpdate("cel", 10));
+ weatherUpdateChannel.change(new WeatherUpdate("cel", 11));
+ weatherUpdateChannel.change(new WeatherUpdate("cel", 12.5));
+
+ weatherUpdateChannel.removeObserver(televisionWatcher);
+ weatherUpdateChannel.change(new WeatherUpdate("cel", 13.5));
+ weatherUpdateChannel.change(new WeatherUpdate("cel", 11.5));
+ weatherUpdateChannel.change(new WeatherUpdate("cel", 9.5));
+ }
+}
diff --git a/low-level-design/src/main/java/com/thealgorithm/observer/example/WeatherUpdate.java b/low-level-design/src/main/java/com/thealgorithm/observer/example/WeatherUpdate.java
new file mode 100644
index 0000000..77b2188
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/observer/example/WeatherUpdate.java
@@ -0,0 +1,23 @@
+package com.thealgorithm.observer.example;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author: Subham Santra
+ */
+@NoArgsConstructor
+@AllArgsConstructor
+@Getter
+@Setter
+public class WeatherUpdate {
+ String scale;
+ double temp;
+
+ @Override
+ public String toString() {
+ return "WeatherUpdate{" + "scale='" + scale + '\'' + ", temp=" + temp + '}';
+ }
+}
diff --git a/low-level-design/src/main/java/com/thealgorithm/observer/example/WeatherUpdateChannel.java b/low-level-design/src/main/java/com/thealgorithm/observer/example/WeatherUpdateChannel.java
new file mode 100644
index 0000000..2e251ed
--- /dev/null
+++ b/low-level-design/src/main/java/com/thealgorithm/observer/example/WeatherUpdateChannel.java
@@ -0,0 +1,14 @@
+package com.thealgorithm.observer.example;
+
+import com.thealgorithm.observer.AbstractObservable;
+import com.thealgorithm.observer.AbstractObserver;
+import java.util.List;
+
+/**
+ * @author: Subham Santra
+ */
+public class WeatherUpdateChannel extends AbstractObservable {
+ public WeatherUpdateChannel(List abstractObservers, WeatherUpdate data) {
+ super(abstractObservers, data);
+ }
+}