diff --git a/dsa-problems/leetcode-problems/1500-1599.md b/dsa-problems/leetcode-problems/1500-1599.md
index cc614bcea..ece183423 100644
--- a/dsa-problems/leetcode-problems/1500-1599.md
+++ b/dsa-problems/leetcode-problems/1500-1599.md
@@ -98,7 +98,7 @@ export const problems = [
"problemName": "1514. Path with Maximum Probability",
"difficulty": "Medium",
"leetCodeLink": "https://leetcode.com/problems/path-with-maximum-probability",
- "solutionLink": "#"
+ "solutionLink": "/dsa-solutions/lc-solutions/1400-1499/path-with-maximum-probability"
},
{
"problemName": "1515. Best Position for a Service Centre",
@@ -518,7 +518,7 @@ export const problems = [
"problemName": "1584. Min Cost to Connect All Points",
"difficulty": "Medium",
"leetCodeLink": "https://leetcode.com/problems/min-cost-to-connect-all-points",
- "solutionLink": "#"
+ "solutionLink": "/dsa-solutions/lc-solutions/1500-1599/min-cost-to-connect-all-points"
},
{
"problemName": "1585. Check If String Is Transformable With Substring Sort Operations",
diff --git a/dsa-problems/leetcode-problems/1600-1699.md b/dsa-problems/leetcode-problems/1600-1699.md
index 63f093c86..de9382094 100644
--- a/dsa-problems/leetcode-problems/1600-1699.md
+++ b/dsa-problems/leetcode-problems/1600-1699.md
@@ -434,7 +434,7 @@ export const problems = [
"problemName": "1670. Design Front Middle Back Queue",
"difficulty": "Medium",
"leetCodeLink": "https://leetcode.com/problems/design-front-middle-back-queue",
- "solutionLink": "#"
+ "solutionLink": "/dsa-solutions/lc-solutions/1600-1699/design-front-middle-back-queue"
},
{
"problemName": "1671. Minimum Number of Removals to Make Mountain Array",
diff --git a/dsa-solutions/lc-solutions/1500-1599/1514-path-with-maximum-probability.md b/dsa-solutions/lc-solutions/1500-1599/1514-path-with-maximum-probability.md
new file mode 100644
index 000000000..21d097d91
--- /dev/null
+++ b/dsa-solutions/lc-solutions/1500-1599/1514-path-with-maximum-probability.md
@@ -0,0 +1,356 @@
+---
+id: path-with-maximum-probability
+title: Path with Maximum Probability
+sidebar_label: 1514. Path with Maximum Probability
+
+tags:
+- Array
+- Graph
+- Heap (Priority Queue)
+- Shortest Path
+
+description: "This is a solution to the Path with Maximum Probability problem on LeetCode."
+---
+
+## Problem Description
+You are given an undirected weighted graph of n nodes (0-indexed), represented by an edge list where `edges[i] = [a, b]` is an undirected edge connecting the nodes a and b with a probability of success of traversing that edge succProb[i].
+
+Given two nodes start and end, find the path with the maximum probability of success to go from start to end and return its success probability.
+
+If there is no path from start to end, return 0. Your answer will be accepted if it differs from the correct answer by at most 1e-5.
+
+### Examples
+**Example 1:**
+
+```
+Input: n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.2], start = 0, end = 2
+Output: 0.25000
+Explanation: There are two paths from start to end, one having a probability of success = 0.2 and the other has 0.5 * 0.5 = 0.25.
+
+```
+
+**Example 2:**
+
+
+```
+Input: n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.3], start = 0, end = 2
+Output: 0.30000
+```
+
+### Constraints
+- `2 <= n <= 10^4`
+- `0 <= start, end < n`
+- `start != end`
+- `0 <= a, b < n`
+- `a != b`
+- `0 <= succProb.length == edges.length <= 2*10^4`
+- `0 <= succProb[i] <= 1`
+- `There is at most one edge between every two nodes.`
+## Solution for Path with Maximum Probability Problem
+### Approach
+#### Main Intuition
+The main intuition behind this code is similar to Dijkstra's algorithm for finding the shortest path, but instead of minimizing distances, it maximizes probabilities. The idea is to iteratively explore the most probable paths using a priority queue to always expand the most promising node (the node with the highest probability of being part of the maximum probability path to the end node).
+
+#### Graph Representation:
+
+- The graph is represented using an adjacency list. Each node has a list of pairs, where each pair consists of an adjacent node and the probability of successfully traversing the edge to that node.
+#### Input Parsing:
+
+- The number of nodes (n) and the edges along with their respective probabilities (edges and succProb) are given as input.
+- The start and end nodes are also provided.
+#### Building the Graph:
+
+- A vector of vectors of pairs (adj) is created to store the adjacency list.
+- For each edge, two entries are added to the adjacency list to ensure the graph is undirected. Each entry contains the adjacent node and the probability of traversing that edge.
+#### Probability Initialization:
+
+- A prob vector is initialized to store the maximum probability of reaching each node from the start node. It is initialized to 0.0 for all nodes.
+- The probability of reaching the start node from itself is set to 1.0 (prob[start] = 1.0).
+#### Priority Queue for Processing Nodes:
+
+- A priority queue (pq) is used to process nodes. This queue helps in processing nodes in the order of their probabilities (although the current implementation uses a max-heap for integer priorities, which is not correct and should use a min-heap for probabilities).
+#### Dijkstra-like Algorithm:
+
+- The algorithm processes nodes from the priority queue. For each node, it checks all its adjacent nodes.
+- For each adjacent node, it calculates the probability of reaching it through the current node (prob[node] * probab).
+- If this new probability is higher than the currently known probability for the adjacent node, it updates the probability and pushes the adjacent node into the priority queue.
+#### Result:
+
+- After processing all reachable nodes, the maximum probability to reach the end node is found in prob[end].
+
+
+
+ #### Implementation
+ ```jsx live
+ function Solution(arr) {
+ var maxProbability = function(n, edges, succProb, start, end) {
+ const p = Array(n).fill(0);
+ const graph = p.reduce((m, _, i) => m.set(i, []), new Map());
+ edges.forEach(([u, v], i) => {
+ graph.get(u).push([v, succProb[i]]);
+ graph.get(v).push([u, succProb[i]]);
+ });
+
+ const queue = [[start, 1]];
+ p[start] = 1;
+
+ for (let [node, currP] of queue) {
+ for (let [adj, nextP] of graph.get(node)) {
+ if (currP * nextP > p[adj]) {
+ p[adj] = currP * nextP;
+ queue.push([adj, p[adj]]);
+ }
+ }
+ }
+
+ return p[end];
+ };
+ const input = [[0,1],[1,2],[0,2]]
+ const n = 3
+ const succProb = [0.5,0.5,0.2]
+ const start=0;
+ const end =2
+ const output = maxProbability(n, input , succProb,start , end)
+ return (
+
+
+ Input:
+ {JSON.stringify(input)}
+
+
+ Output: {output.toString()}
+
+
+ );
+ }
+ ```
+
+ #### Complexity Analysis
+
+ - Time Complexity: $O(edges*log(n)) $
+ - Space Complexity: $ O(n)$
+
+ ## Code in Different Languages
+
+
+
+ ```javascript
+ function maxProbability(n, edges, succProb, start, end) {
+ let adj = Array.from({ length: n }, () => []);
+
+ for (let i = 0; i < edges.length; i++) {
+ adj[edges[i][0]].push([edges[i][1], succProb[i]]);
+ adj[edges[i][1]].push([edges[i][0], succProb[i]]);
+ }
+
+ let prob = new Array(n).fill(0.0);
+ let pq = new MaxPriorityQueue({ priority: x => x[1] });
+
+ prob[start] = 1.0;
+ pq.enqueue([start, 1.0]);
+
+ while (!pq.isEmpty()) {
+ let [node, nodeProb] = pq.dequeue().element;
+
+ for (let [adjNode, probab] of adj[node]) {
+ if (prob[node] * probab > prob[adjNode]) {
+ prob[adjNode] = prob[node] * probab;
+ pq.enqueue([adjNode, prob[adjNode]]);
+ }
+ }
+ }
+
+ return prob[end];
+}
+
+ ```
+
+
+
+
+ ```typescript
+ class Solution {
+ maxProbability(n: number, edges: number[][], succProb: number[], start: number, end: number): number {
+ let adj: Array<[number, number][]> = Array.from({ length: n }, () => []);
+
+ for (let i = 0; i < edges.length; i++) {
+ adj[edges[i][0]].push([edges[i][1], succProb[i]]);
+ adj[edges[i][1]].push([edges[i][0], succProb[i]]);
+ }
+
+ let prob: number[] = new Array(n).fill(0.0);
+ let pq = new MaxPriorityQueue({ priority: (x: [number, number]) => x[1] });
+
+ prob[start] = 1.0;
+ pq.enqueue([start, 1.0]);
+
+ while (!pq.isEmpty()) {
+ let [node, nodeProb] = pq.dequeue().element;
+
+ for (let [adjNode, probab] of adj[node]) {
+ if (prob[node] * probab > prob[adjNode]) {
+ prob[adjNode] = prob[node] * probab;
+ pq.enqueue([adjNode, prob[adjNode]]);
+ }
+ }
+ }
+
+ return prob[end];
+ }
+}
+
+ ```
+
+
+
+ ```python
+ import heapq
+from typing import List
+
+class Solution:
+ def maxProbability(self, n: int, edges: List[List[int]], succProb: List[float], start: int, end: int) -> float:
+ adj = [[] for _ in range(n)]
+
+ for i in range(len(edges)):
+ adj[edges[i][0]].append((edges[i][1], succProb[i]))
+ adj[edges[i][1]].append((edges[i][0], succProb[i]))
+
+ prob = [0.0] * n
+ pq = []
+
+ prob[start] = 1.0
+ heapq.heappush(pq, (-1.0, start))
+
+ while pq:
+ nodeProb, node = heapq.heappop(pq)
+ nodeProb = -nodeProb
+
+ for adjNode, probab in adj[node]:
+ if prob[node] * probab > prob[adjNode]:
+ prob[adjNode] = prob[node] * probab
+ heapq.heappush(pq, (-prob[adjNode], adjNode))
+
+ return prob[end]
+
+ ```
+
+
+
+
+ ```java
+ import java.util.*;
+
+class Solution {
+ public double maxProbability(int n, int[][] edges, double[] succProb, int start, int end) {
+ List>[] adj = new ArrayList[n];
+ for (int i = 0; i < n; i++) {
+ adj[i] = new ArrayList<>();
+ }
+
+ for (int i = 0; i < edges.length; i++) {
+ adj[edges[i][0]].add(new Pair<>(edges[i][1], succProb[i]));
+ adj[edges[i][1]].add(new Pair<>(edges[i][0], succProb[i]));
+ }
+
+ double[] prob = new double[n];
+ PriorityQueue> pq = new PriorityQueue<>((a, b) -> Double.compare(b.getValue(), a.getValue()));
+
+ prob[start] = 1.0;
+ pq.add(new Pair<>(start, 1.0));
+
+ while (!pq.isEmpty()) {
+ Pair nodePair = pq.poll();
+ int node = nodePair.getKey();
+ double nodeProb = nodePair.getValue();
+
+ for (Pair it : adj[node]) {
+ int adjNode = it.getKey();
+ double probab = it.getValue();
+
+ if (prob[node] * probab > prob[adjNode]) {
+ prob[adjNode] = prob[node] * probab;
+ pq.add(new Pair<>(adjNode, prob[adjNode]));
+ }
+ }
+ }
+
+ return prob[end];
+ }
+
+ static class Pair {
+ private final K key;
+ private final V value;
+
+ public Pair(K key, V value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public K getKey() {
+ return key;
+ }
+
+ public V getValue() {
+ return value;
+ }
+ }
+}
+
+ ```
+
+
+
+
+ ```cpp
+ class Solution {
+public:
+ double maxProbability(int n, vector>& edges, vector& succProb, int start, int end) {
+ vector>adj[n];
+
+ for(int i=0;iprob(n,0.0);
+ priority_queue pq;
+
+ prob[start]=1.0;
+
+ pq.push(start);
+
+ while(!pq.empty())
+ {
+ int node= pq.top();
+ pq.pop();
+
+ for(auto it: adj[node])
+ {
+ int adjNode=it.first;
+ double probab=it.second;
+
+ if(prob[node]*probab>prob[adjNode] )
+ {
+ pq.push(adjNode);
+ prob[adjNode]=prob[node]*probab;
+ }
+ }
+ }
+
+ return prob[end];
+ }
+};
+```
+
+
+
+
+
+
+## References
+
+- **LeetCode Problem**: [Path with Maximum Probability](https://leetcode.com/problems/path-with-maximum-probability)
+
+- **Solution Link**: [LeetCode Solution](https://leetcode.com/problems/path-with-maximum-probability/solutions)
+
diff --git a/dsa-solutions/lc-solutions/1500-1599/1584-min-cost-to-connect-all-points.md b/dsa-solutions/lc-solutions/1500-1599/1584-min-cost-to-connect-all-points.md
new file mode 100644
index 000000000..064550c64
--- /dev/null
+++ b/dsa-solutions/lc-solutions/1500-1599/1584-min-cost-to-connect-all-points.md
@@ -0,0 +1,378 @@
+---
+id: min-cost-to-connect-all-points
+title: Min Cost to Connect All Points
+sidebar_label: 1584.Min Cost to Connect All Points
+
+tags:
+- Array
+- Union Find
+- Graph
+- Minimum Spanning Tree
+
+description: "This is a solution to the Min Cost to Connect All Points problem on LeetCode."
+---
+
+## Problem Description
+You are given an array points representing integer coordinates of some points on a 2D-plane, where `points[i] = [xi, yi].`
+
+The cost of connecting two points [xi, yi] and [xj, yj] is the manhattan distance between them: `|xi - xj| + |yi - yj|`, where |val| denotes the absolute value of val.
+
+Return the minimum cost to make all points connected. All points are connected if there is exactly one simple path between any two points.
+
+### Examples
+**Example 1:**
+
+```
+Input: points = [[0,0],[2,2],[3,10],[5,2],[7,0]]
+Output: 20
+Explanation:
+
+We can connect the points as shown above to get the minimum cost of 20.
+Notice that there is a unique path between every pair of points.
+
+```
+
+### Constraints
+- `1 <= points.length <= 1000`
+- `-10^6 <= xi, yi <= 10^6`
+- `All pairs (xi, yi) are distinct.`
+
+## Solution for Min Cost to Connect All Points
+### Approach
+#### Prim's algorithm:
+
+- Prim's algorithm is an algorithm for solving the optimization problem of finding the minimum spanning tree in a weighted connected graph within graph theory. A minimum spanning tree is a subset of the edges of the graph that forms a tree containing all vertices while minimizing the total weight of those edges.
+
+#### Overview of the Algorithm:
+
+- Calculate the distances between each pair of points and use Prim's algorithm to form the minimum spanning tree.
+- Start from an initial point, mark it as visited, and select the point with the smallest distance among the unvisited points.
+- Calculate the distances from the selected point to the unvisited points and store them in a cache.
+- Add the minimum cost edge to the priority queue using the distances from the cache.
+- Repeat the above steps until all points are visited, and calculate the minimum cost.
+#### Specific Steps:
+
+#### Initial State:
+
+- n: Number of points
+- min_cost: Minimum cost (initially 0) and return value
+- visited: A list to indicate if each point is visited (initially all False)
+- pq: Priority queue (initially (0, 0) indicating starting from point 0 with cost 0)
+- cache: Dictionary for caching distances (initially empty)
+#### Each Step:
+
+- Pop cost and point from pq (start from the initial point).
+- If the point is already visited, skip this point.
+- Otherwise, mark this point as visited and add the current cost to the minimum cost.
+- Calculate distances from this point to all unvisited points and store them in the cache. Update the cache if the new distance is smaller.
+- Add the point with the smallest distance among the unvisited points to the priority queue using distances from the cache.
+- Repeat steps 3 to 5 until all points are visited.
+- Return the final minimum cost.
+
+
+
+
+
+ #### Implementation
+ ```jsx live
+ function Solution(arr) {
+ var minCostConnectPoints = function(points) {
+ let cost = 0;
+ const n = points.length;
+ const dist = Array(n).fill(Infinity);
+ dist[0] = 0;
+ let next = 0;
+
+ for (let step = 1; step < n; step++) {
+ let min = Infinity;
+ let point = -1;
+ for (let i = 1; i < n; i++) {
+ if (dist[i] > 0) {
+ dist[i] = Math.min(dist[i], Math.abs(points[i][0] - points[next][0]) + Math.abs(points[i][1] - points[next][1]));
+ if (dist[i] < min) {
+ min = dist[i];
+ point = i;
+ }
+ }
+ }
+ cost += min;
+ dist[point] = 0;
+ next = point;
+ }
+
+ return cost;
+ };
+ const input = [[0,0],[2,2],[3,10],[5,2],[7,0]]
+ const output =minCostConnectPoints(input)
+ return (
+
+
+ Input:
+ {JSON.stringify(input)}
+
+
+ Output: {output.toString()}
+
+
+ );
+ }
+ ```
+
+ #### Complexity Analysis
+
+ - Time Complexity: $O(n^2 * log(n)) $
+ - Space Complexity: $ O(n)$
+
+ ## Code in Different Languages
+
+
+
+ ```javascript
+ manhattDist(v1, v2) {
+ return Math.abs(v1[0] - v2[0]) + Math.abs(v1[1] - v2[1]);
+ }
+
+ minCostConnectPoints(points) {
+ const n = points.length;
+ const adj = Array.from({ length: n }, () => []);
+
+ for (let i = 0; i < n; i++) {
+ for (let j = i + 1; j < n; j++) {
+ const dist = this.manhattDist(points[i], points[j]);
+ adj[i].push([j, dist]);
+ adj[j].push([i, dist]);
+ }
+ }
+
+ const pq = new MinPriorityQueue({ priority: x => x[0] });
+ const vis = Array(n).fill(false);
+ pq.enqueue([0, 0]);
+ let cost = 0;
+
+ while (!pq.isEmpty()) {
+ const [topEdgwWt, currNode] = pq.dequeue().element;
+
+ if (vis[currNode]) continue;
+ vis[currNode] = true;
+ cost += topEdgwWt;
+
+ for (const [adjPoint, edWt] of adj[currNode]) {
+ if (!vis[adjPoint]) {
+ pq.enqueue([edWt, adjPoint]);
+ }
+ }
+ }
+
+ return cost;
+ }
+ ```
+
+
+
+
+ ```typescript
+ class Solution {
+ manhattDist(v1: number[], v2: number[]): number {
+ return Math.abs(v1[0] - v2[0]) + Math.abs(v1[1] - v2[1]);
+ }
+
+ minCostConnectPoints(points: number[][]): number {
+ const n = points.length;
+ const adj: [number, number][][] = Array.from({ length: n }, () => []);
+
+ for (let i = 0; i < n; i++) {
+ for (let j = i + 1; j < n; j++) {
+ const dist = this.manhattDist(points[i], points[j]);
+ adj[i].push([j, dist]);
+ adj[j].push([i, dist]);
+ }
+ }
+
+ const pq = new MinPriorityQueue({ priority: (x: [number, number]) => x[0] });
+ const vis = Array(n).fill(false);
+ pq.enqueue([0, 0]);
+ let cost = 0;
+
+ while (!pq.isEmpty()) {
+ const [topEdgwWt, currNode] = pq.dequeue().element;
+
+ if (vis[currNode]) continue;
+ vis[currNode] = true;
+ cost += topEdgwWt;
+
+ for (const [adjPoint, edWt] of adj[currNode]) {
+ if (!vis[adjPoint]) {
+ pq.enqueue([edWt, adjPoint]);
+ }
+ }
+ }
+
+ return cost;
+ }
+}
+
+ ```
+
+
+
+ ```python
+ import heapq
+
+class Solution:
+ def manhattDist(self, v1, v2):
+ return abs(v1[0] - v2[0]) + abs(v1[1] - v2[1])
+
+ def minCostConnectPoints(self, points):
+ n = len(points)
+ adj = [[] for _ in range(n)]
+
+ for i in range(n):
+ for j in range(i + 1, n):
+ dist = self.manhattDist(points[i], points[j])
+ adj[i].append((j, dist))
+ adj[j].append((i, dist))
+
+ pq = [(0, 0)] # (distance, point)
+ vis = [False] * n
+ cost = 0
+
+ while pq:
+ topEdgwWt, currNode = heapq.heappop(pq)
+
+ if vis[currNode]:
+ continue
+ vis[currNode] = True
+ cost += topEdgwWt
+
+ for adjPoint, edWt in adj[currNode]:
+ if not vis[adjPoint]:
+ heapq.heappush(pq, (edWt, adjPoint))
+
+ return cost
+
+ ```
+
+
+
+
+ ```java
+ import java.util.*;
+
+class Solution {
+ private int manhattDist(int[] v1, int[] v2) {
+ return Math.abs(v1[0] - v2[0]) + Math.abs(v1[1] - v2[1]);
+ }
+
+ public int minCostConnectPoints(int[][] points) {
+ int n = points.length;
+ List> adj = new ArrayList<>();
+
+ for (int i = 0; i < n; i++) {
+ adj.add(new ArrayList<>());
+ }
+
+ for (int i = 0; i < n; i++) {
+ for (int j = i + 1; j < n; j++) {
+ int dist = manhattDist(points[i], points[j]);
+ adj.get(i).add(new int[]{j, dist});
+ adj.get(j).add(new int[]{i, dist});
+ }
+ }
+
+ PriorityQueue pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
+ boolean[] vis = new boolean[n];
+ pq.add(new int[]{0, 0}); // {distance, point}
+ int cost = 0;
+
+ while (!pq.isEmpty()) {
+ int[] curr = pq.poll();
+ int topEdgwWt = curr[0];
+ int currNode = curr[1];
+
+ if (vis[currNode]) continue;
+ vis[currNode] = true;
+ cost += topEdgwWt;
+
+ for (int[] neighbor : adj.get(currNode)) {
+ int adjPoint = neighbor[0];
+ int edWt = neighbor[1];
+ if (!vis[adjPoint]) {
+ pq.add(new int[]{edWt, adjPoint});
+ }
+ }
+ }
+
+ return cost;
+ }
+}
+
+ ```
+
+
+
+
+
+ ```cpp
+ class Solution {
+public:
+ int manhattDist(vector&v1 , vector&v2)
+ {
+ return abs(abs(v1[0]-v2[0]) + abs(v1[1]-v2[1]));
+ }
+ int minCostConnectPoints(vector>& points) {
+ int n = points.size();
+ vector> adj[n]; //{point , cost or Manhattan dist}
+
+ //we have to make a adjacency list fom every point to every other point
+ for(int i=0; i , vector> , greater> > pq;
+ // {distance , point}
+ vector vis(n,0);
+ pq.push({0,0}); //starting from 0 as source
+ int Cost=0;
+ while(!pq.empty())
+ {
+ auto it = pq.top();
+ pq.pop();
+ int CurrNode = it.second ;
+ int topEdgwWt = it.first;
+
+ if(vis[CurrNode]==1) continue;
+
+ vis[CurrNode]=1;
+
+ Cost+=topEdgwWt;
+ for(auto it: adj[CurrNode])
+ {
+ int adjPoint=it.first;
+ int edWt=it.second;
+ if(!vis[adjPoint])
+ {
+ pq.push({edWt , adjPoint});
+ }
+ }
+ }
+ return Cost;
+ }
+};
+```
+
+
+
+
+
+
+## References
+
+- **LeetCode Problem**: [ Min Cost to Connect All Points](https://leetcode.com/problems/min-cost-to-connect-all-points/description/)
+
+- **Solution Link**: [LeetCode Solution](https://leetcode.com/problems/min-cost-to-connect-all-points/description/)
+
diff --git a/dsa-solutions/lc-solutions/1600-1699/1670-design-front-middle-back-queue.md b/dsa-solutions/lc-solutions/1600-1699/1670-design-front-middle-back-queue.md
new file mode 100644
index 000000000..7039ce008
--- /dev/null
+++ b/dsa-solutions/lc-solutions/1600-1699/1670-design-front-middle-back-queue.md
@@ -0,0 +1,481 @@
+---
+id: design-front-middle-back-queue
+title: Design Front Middle Back Queue
+sidebar_label: 1670.Design Front Middle Back Queue
+
+tags:
+- Array
+- Linked List
+- Design
+- Queue
+- Data Stream
+
+description: "This is a solution to theDesign Front Middle Back Queue problem on LeetCode."
+---
+
+## Problem Description
+Design a queue that supports push and pop operations in the front, middle, and back.
+
+Implement the FrontMiddleBack class:
+
+- FrontMiddleBack() Initializes the queue.
+- void pushFront(int val) Adds val to the front of the queue.
+- void pushMiddle(int val) Adds val to the middle of the queue.
+- void pushBack(int val) Adds val to the back of the queue.
+- int popFront() Removes the front element of the queue and returns it. If the queue is empty, return -1.
+- int popMiddle() Removes the middle element of the queue and returns it. If the queue is empty, return -1.
+- int popBack() Removes the back element of the queue and returns it. If the queue is empty, return -1.
+- Notice that when there are two middle position choices, the operation is performed on the frontmost middle position choice. For example:
+
+- Pushing 6 into the middle of [1, 2, 3, 4, 5] results in [1, 2, 6, 3, 4, 5].
+- Popping the middle from [1, 2, 3, 4, 5, 6] returns 3 and results in [1, 2, 4, 5, 6].
+
+### Examples
+**Example 1:**
+```
+Input:
+["FrontMiddleBackQueue", "pushFront", "pushBack", "pushMiddle", "pushMiddle", "popFront", "popMiddle", "popMiddle", "popBack", "popFront"]
+[[], [1], [2], [3], [4], [], [], [], [], []]
+Output:
+[null, null, null, null, null, 1, 3, 4, 2, -1]
+
+Explanation:
+FrontMiddleBackQueue q = new FrontMiddleBackQueue();
+q.pushFront(1); // [1]
+q.pushBack(2); // [1, 2]
+q.pushMiddle(3); // [1, 3, 2]
+q.pushMiddle(4); // [1, 4, 3, 2]
+q.popFront(); // return 1 -> [4, 3, 2]
+q.popMiddle(); // return 3 -> [4, 2]
+q.popMiddle(); // return 4 -> [2]
+q.popBack(); // return 2 -> []
+q.popFront(); // return -1 -> [] (The queue is empty)
+
+```
+
+### Constraints
+- `1 <= val <= 10^9`
+- At most 1000 calls will be made to pushFront, pushMiddle, pushBack, popFront, popMiddle, and popBack.
+## Solution for Design Front Middle Back Queue
+### Approach
+#### Data Structure
+
+- **Deque (Double-ended Queue):** A deque is used to store the elements. It allows for efficient addition and removal of elements from both the front and the back. This is crucial for implementing the required operations efficiently.
+
+#### Operations
+
+1. **Initialization:**
+ - The constructor initializes an empty deque.
+
+2. **Push Operations:**
+ - **pushFront(int val):**
+ - Adds `val` to the front of the deque.
+ - This is done using the `push_front` method in C++ or the equivalent method in other languages (e.g., `unshift` in JavaScript, `appendleft` in Python, `addFirst` in Java).
+ - **pushMiddle(int val):**
+ - Adds `val` to the middle of the deque.
+ - The middle index is calculated as `size / 2`. If the size is even, it places the element just before the second half; if odd, it places it in the middle.
+ - Inserting at this position can be done using the `insert` method in most languages.
+ - **pushBack(int val):**
+ - Adds `val` to the back of the deque.
+ - This is done using the `push_back` method in C++ or the equivalent method in other languages (e.g., `push` in JavaScript, `append` in Python, `addLast` in Java).
+
+3. **Pop Operations:**
+ - **popFront():**
+ - Removes and returns the element from the front of the deque.
+ - If the deque is empty, it returns `-1`.
+ - This is done using the `pop_front` method in C++ or the equivalent method in other languages (e.g., `shift` in JavaScript, `popleft` in Python, `removeFirst` in Java).
+ - **popMiddle():**
+ - Removes and returns the middle element of the deque.
+ - The middle index is calculated as `(size - 1) / 2`. This ensures the correct middle element is chosen whether the size is odd or even.
+ - If the deque is empty, it returns `-1`.
+ - The element at this index is removed using the `erase` method in C++ or the equivalent method in other languages (e.g., `splice` in JavaScript, direct indexing in Python, manual traversal in Java).
+ - **popBack():**
+ - Removes and returns the element from the back of the deque.
+ - If the deque is empty, it returns `-1`.
+ - This is done using the `pop_back` method in C++ or the equivalent method in other languages (e.g., `pop` in JavaScript, `pop` in Python, `removeLast` in Java).
+
+## Intuition
+
+The main intuition behind using a deque is that it provides efficient O(1) time complexity for adding and removing elements from both ends. For the middle operations, although inserting and removing from the middle of a deque is generally O(n) due to shifting elements, the deque allows straightforward and flexible indexing which simplifies implementation.
+
+
+
+
+
+ #### Implementation
+ ```jsx live
+ function Solution(arr) {
+ var FrontMiddleBackQueue = function() {
+ this.queue = [];
+ };
+
+ /**
+ * @param {number} val
+ * @return {void}
+ */
+ FrontMiddleBackQueue.prototype.pushFront = function(val) {
+ this.queue.unshift(val);
+ };
+
+ /**
+ * @param {number} val
+ * @return {void}
+ */
+ FrontMiddleBackQueue.prototype.pushMiddle = function(val) {
+ let middle = Math.floor(this.queue.length / 2);
+ this.queue.splice(middle, 0, val)
+ };
+
+ /**
+ * @param {number} val
+ * @return {void}
+ */
+ FrontMiddleBackQueue.prototype.pushBack = function(val) {
+ this.queue.push(val);
+ };
+
+ /**
+ * @return {number}
+ */
+ FrontMiddleBackQueue.prototype.popFront = function() {
+ if(!this.queue.length) return -1;
+ return this.queue.shift();
+ };
+
+ /**
+ * @return {number}
+ */
+ FrontMiddleBackQueue.prototype.popMiddle = function() {
+ if(!this.queue.length) return -1;
+ let middle = Math.floor(this.queue.length / 2);
+ if(this.queue.length % 2 == 0) middle--;
+ return this.queue.splice(middle, 1);
+ };
+
+ /**
+ * @return {number}
+ */
+ FrontMiddleBackQueue.prototype.popBack = function() {
+ if(!this.queue.length) return -1;
+ return this.queue.pop();
+ };
+
+ /**
+ * Your FrontMiddleBackQueue object will be instantiated and called as such:
+ * var obj = new FrontMiddleBackQueue()
+ * obj.pushFront(val)
+ * obj.pushMiddle(val)
+ * obj.pushBack(val)
+ * var param_4 = obj.popFront()
+ * var param_5 = obj.popMiddle()
+ * var param_6 = obj.popBack()
+ */
+ const input = "["FrontMiddleBackQueue", "pushFront", "pushBack", "pushMiddle", "pushMiddle", "popFront", "popMiddle", "popMiddle", "popBack", "popFront"]
+ [[], [1], [2], [3], [4], [], [], [], [], []]"
+ const output =[null, null, null, null, null, 1, 3, 4, 2, -1]
+ return (
+
+
+ Input:
+ {JSON.stringify(input)}
+
+
+ Output: {output.toString()}
+
+
+ );
+ }
+ ```
+
+ #### Complexity Analysis
+
+ - Time Complexity: $O(1) $
+ - Space Complexity: $ O(n)$ , where n is the total number we are inserting
+
+ ## Code in Different Languages
+
+
+
+ ```javascript
+ var FrontMiddleBackQueue = function() {
+ this.queue = [];
+};
+
+/**
+ * @param {number} val
+ * @return {void}
+ */
+FrontMiddleBackQueue.prototype.pushFront = function(val) {
+ this.queue.unshift(val);
+};
+
+/**
+ * @param {number} val
+ * @return {void}
+ */
+FrontMiddleBackQueue.prototype.pushMiddle = function(val) {
+ let middle = Math.floor(this.queue.length / 2);
+ this.queue.splice(middle, 0, val)
+};
+
+/**
+ * @param {number} val
+ * @return {void}
+ */
+FrontMiddleBackQueue.prototype.pushBack = function(val) {
+ this.queue.push(val);
+};
+
+/**
+ * @return {number}
+ */
+FrontMiddleBackQueue.prototype.popFront = function() {
+ if(!this.queue.length) return -1;
+ return this.queue.shift();
+};
+
+/**
+ * @return {number}
+ */
+FrontMiddleBackQueue.prototype.popMiddle = function() {
+ if(!this.queue.length) return -1;
+ let middle = Math.floor(this.queue.length / 2);
+ if(this.queue.length % 2 == 0) middle--;
+ return this.queue.splice(middle, 1);
+};
+
+/**
+ * @return {number}
+ */
+FrontMiddleBackQueue.prototype.popBack = function() {
+ if(!this.queue.length) return -1;
+ return this.queue.pop();
+};
+
+/**
+ * Your FrontMiddleBackQueue object will be instantiated and called as such:
+ * var obj = new FrontMiddleBackQueue()
+ * obj.pushFront(val)
+ * obj.pushMiddle(val)
+ * obj.pushBack(val)
+ * var param_4 = obj.popFront()
+ * var param_5 = obj.popMiddle()
+ * var param_6 = obj.popBack()
+ */
+ ```
+
+
+
+
+ ```typescript
+ class FrontMiddleBackQueue {
+ private dq: number[];
+
+ constructor() {
+ this.dq = [];
+ }
+
+ pushFront(val: number): void {
+ this.dq.unshift(val);
+ }
+
+ pushMiddle(val: number): void {
+ const size = this.dq.length;
+ this.dq.splice(Math.floor(size / 2), 0, val);
+ }
+
+ pushBack(val: number): void {
+ this.dq.push(val);
+ }
+
+ popFront(): number {
+ if (this.dq.length === 0) return -1;
+ return this.dq.shift()!;
+ }
+
+ popMiddle(): number {
+ if (this.dq.length === 0) return -1;
+ const size = this.dq.length;
+ const middleIndex = Math.floor((size - 1) / 2);
+ return this.dq.splice(middleIndex, 1)[0];
+ }
+
+ popBack(): number {
+ if (this.dq.length === 0) return -1;
+ return this.dq.pop()!;
+ }
+}
+
+ ```
+
+
+
+ ```python
+ from collections import deque
+
+class FrontMiddleBackQueue:
+ def __init__(self):
+ self.dq = deque()
+
+ def pushFront(self, val: int) -> None:
+ self.dq.appendleft(val)
+
+ def pushMiddle(self, val: int) -> None:
+ size = len(self.dq)
+ self.dq.insert(size // 2, val)
+
+ def pushBack(self, val: int) -> None:
+ self.dq.append(val)
+
+ def popFront(self) -> int:
+ if not self.dq:
+ return -1
+ return self.dq.popleft()
+
+ def popMiddle(self) -> int:
+ if not self.dq:
+ return -1
+ size = len(self.dq)
+ middleIndex = (size - 1) // 2
+ return self.dq.pop(middleIndex)
+
+ def popBack(self) -> int:
+ if not self.dq:
+ return -1
+ return self.dq.pop()
+
+ ```
+
+
+
+
+ ```java
+ import java.util.Deque;
+import java.util.LinkedList;
+
+class FrontMiddleBackQueue {
+ private Deque dq;
+
+ public FrontMiddleBackQueue() {
+ dq = new LinkedList<>();
+ }
+
+ public void pushFront(int val) {
+ dq.addFirst(val);
+ }
+
+ public void pushMiddle(int val) {
+ int size = dq.size();
+ int middleIndex = size / 2;
+ if (middleIndex == size) {
+ dq.add(val);
+ } else {
+ Deque temp = new LinkedList<>();
+ for (int i = 0; i < middleIndex; i++) {
+ temp.add(dq.removeFirst());
+ }
+ dq.addFirst(val);
+ while (!temp.isEmpty()) {
+ dq.addFirst(temp.removeLast());
+ }
+ }
+ }
+
+ public void pushBack(int val) {
+ dq.addLast(val);
+ }
+
+ public int popFront() {
+ if (dq.isEmpty()) return -1;
+ return dq.removeFirst();
+ }
+
+ public int popMiddle() {
+ if (dq.isEmpty()) return -1;
+ int size = dq.size();
+ int middleIndex = (size - 1) / 2;
+ Deque temp = new LinkedList<>();
+ for (int i = 0; i < middleIndex; i++) {
+ temp.add(dq.removeFirst());
+ }
+ int middle = dq.removeFirst();
+ while (!temp.isEmpty()) {
+ dq.addFirst(temp.removeLast());
+ }
+ return middle;
+ }
+
+ public int popBack() {
+ if (dq.isEmpty()) return -1;
+ return dq.removeLast();
+ }
+}
+
+ ```
+
+
+
+
+
+ ```cpp
+ class FrontMiddleBackQueue {
+public:
+ deque dq;
+ FrontMiddleBackQueue() {
+
+ }
+
+ void pushFront(int val) {
+ dq.push_front(val);
+ }
+
+ void pushMiddle(int val) {
+ int size = dq.size();
+ dq.insert(dq.begin()+size/2,val);
+ }
+
+ void pushBack(int val) {
+ dq.push_back(val);
+ }
+
+ int popFront() {
+ if (dq.empty()) return -1;
+ int x = dq.front();
+ dq.pop_front();
+ return x;
+ }
+
+ int popMiddle() {
+ if (dq.empty()) return -1;
+
+ int size = dq.size();
+ int middleIndex = (size - 1) / 2;
+ int element = dq[middleIndex];
+
+ dq.erase(dq.begin() + middleIndex);
+
+ return element;
+ }
+
+
+ int popBack() {
+ if (dq.empty()) return -1;
+ int x = dq.back();
+ dq.pop_back();
+ return x;
+ }
+};
+
+```
+
+
+
+
+
+
+## References
+
+- **LeetCode Problem**: [Design Front Middle Back Queue](https://leetcode.com/problems/design-front-middle-back-queue/description/)
+
+- **Solution Link**: [LeetCode Solution](https://leetcode.com/problems/design-front-middle-back-queue/solution)
+