# Algorithm Problem Solving Patterns

## Sliding Window​

The sliding window technique is used for problems that involve arrays or lists where you need to find a subarray (or sublist) that satisfies certain conditions. It's particularly useful for problems involving sums, averages, or finding specific subarray properties within a given window size.

Example Problem: Find the maximum sum of a subarray of size k.

``function maxSumSubarray(arr, k) {  let maxSum = 0;  let windowSum = 0;  // Calculate the sum of the first window  for (let i = 0; i < k; i++) {    windowSum += arr[i];  }  maxSum = windowSum;  // Slide the window from the start to the end of the array  for (let i = k; i < arr.length; i++) {    windowSum += arr[i] - arr[i - k];    maxSum = Math.max(maxSum, windowSum);  }  return maxSum;}// Example usageconst arr = [1, 3, 2, 6, -1, 4, 1, 8, 2];const k = 3;console.log(maxSumSubarray(arr, k)); // Output: 14 (6, -1, 4)``

## Two Pointers​

The two pointers technique is useful for problems involving sorted arrays or linked lists. It involves using two pointers to iterate through the array from different directions or positions, usually starting at the beginning and end.

Example Problem: Given a sorted array, find two numbers that add up to a given target.

``function twoSumSorted(arr, target) {  let left = 0;  let right = arr.length - 1;  while (left < right) {    const currentSum = arr[left] + arr[right];    if (currentSum === target) {      return [arr[left], arr[right]];    } else if (currentSum < target) {      left++;    } else {      right--;    }  }  return null;}// Example usageconst arr = [1, 2, 3, 4, 6];const target = 6;console.log(twoSumSorted(arr, target)); // Output: [2, 4]``

## Fast and Slow Pointers (Tortoise and Hare)​

This technique involves using two pointers that move at different speeds (one fast and one slow). It is often used to detect cycles in linked lists or arrays.

Example Problem: Detect if a linked list has a cycle.

``class ListNode {  constructor(value = 0, next = null) {    this.value = value;    this.next = next;  }}function hasCycle(head) {  let slow = head;  let fast = head;  while (fast !== null && fast.next !== null) {    slow = slow.next;    fast = fast.next.next;    if (slow === fast) {      return true;    }  }  return false;}// Example usage// Creating a linked list with a cycleconst node1 = new ListNode(3);const node2 = new ListNode(2);const node3 = new ListNode(0);const node4 = new ListNode(-4);node1.next = node2;node2.next = node3;node3.next = node4;node4.next = node2; // Cycle hereconsole.log(hasCycle(node1)); // Output: true``

## Toplogical Sorting​

Topological sorting is used to order the vertices of a directed acyclic graph (DAG) in a linear sequence such that for every directed edge `u -> v`, vertex `u` comes before `v`.

`Example Problem`: Perform a topological sort on a directed acyclic graph.

``function topologicalSort(graph) {  const stack = [];  const visited = new Set();  function dfs(node) {    if (visited.has(node)) return;    visited.add(node);    for (let neighbor of graph[node]) {      dfs(neighbor);    }    stack.push(node);  }  for (let node in graph) {    if (!visited.has(node)) {      dfs(node);    }  }  return stack.reverse();}// Example usageconst graph = {  5: [2, 0],  4: [0, 1],  3: [1],  2: [3],  1: [],  0: [],};console.log(topologicalSort(graph)); // Output: [5, 4, 2, 3, 1, 0]``

## Union Find (Disjoint Set)​

The union-find (or disjoint-set) is a data structure that keeps track of elements partitioned into disjoint (non-overlapping) sets. It supports two primary operations: finding the set a particular element is in, and merging two sets.

Example Problem: Implement union-find to detect cycles in an undirected graph.

``class UnionFind {  constructor(size) {    this.parent = Array.from({length: size}, (_, index) => index);    this.rank = Array(size).fill(0);  }  find(node) {    if (this.parent[node] !== node) {      this.parent[node] = this.find(this.parent[node]); // Path compression    }    return this.parent[node];  }  union(node1, node2) {    const root1 = this.find(node1);    const root2 = this.find(node2);    if (root1 !== root2) {      if (this.rank[root1] > this.rank[root2]) {        this.parent[root2] = root1;      } else if (this.rank[root1] < this.rank[root2]) {        this.parent[root1] = root2;      } else {        this.parent[root2] = root1;        this.rank[root1]++;      }    }  }  connected(node1, node2) {    return this.find(node1) === this.find(node2);  }}// Example usageconst uf = new UnionFind(5);uf.union(0, 1);uf.union(1, 2);uf.union(3, 4);console.log(uf.connected(0, 2)); // Output: trueconsole.log(uf.connected(0, 3)); // Output: false``

# Automated Amazon Reports

Automatically download Amazon Seller and Advertising reports to a private database. View beautiful, on demand, exportable performance reports.