Skip to content

Commit

Permalink
add(leetcodes-pattern): window slide pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
thutasann committed Sep 17, 2024
1 parent 627975a commit fe5f26d
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 0 deletions.
1 change: 1 addition & 0 deletions node-concepts/src/leetcodes/leetcodes-patterns/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ console.log('----------------------------\n');

SlidingWindowPatternUsage.maxSumSubarrayUsage();
SlidingWindowPatternUsage.longestSubstringWithKDistinctUsage();
SlidingWindowPatternUsage.maxTrafficInWindowUsage();
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>DOM Optimization using Sliding Window Technique</title>
<style>
#container {
height: 300px;
overflow-y: scroll;
border: 1px solid black;
position: relative;
}
.item {
height: 50px;
border-bottom: 1px solid #ccc;
position: absolute;
width: 100%;
}
</style>
</head>
<body>
<h1>Open in Browser</h1>
<div id="container"></div>

<script>
const totalItems = 10000; // Total items in our data
const itemHeight = 50; // Height of each item in pixels
const container = document.getElementById('container');
let startIndex = 0; // Start index for the visible items
let endIndex = Math.min(
totalItems,
Math.ceil(container.clientHeight / itemHeight) + startIndex,
);

// Generate an array of dummy data (e.g., "Item 1", "Item 2", etc.)
const generateItems = (count) =>
Array.from({ length: count }, (_, index) => `Item ${index + 1}`);

const items = generateItems(totalItems); // Generate the full list of items

// Function to render a range of items
function renderItems(start, end) {
container.innerHTML = '';

// Render only the items in the visible range
for (let i = start; i < end; i++) {
const itemDiv = document.createElement('div');
itemDiv.classList.add('item');
itemDiv.style.top = `${i * itemHeight}px`;
itemDiv.id = `item-${i + 1}`;
itemDiv.textContent = items[i];
container.appendChild(itemDiv);
}
}

// Initialize the container with items
renderItems(startIndex, endIndex);

// Scroll event handler
container.addEventListener('scroll', () => {
const scrollTop = container.scrollTop;
startIndex = Math.floor(scrollTop / itemHeight);
endIndex = Math.min(
totalItems,
Math.ceil((scrollTop + container.clientHeight) / itemHeight),
);

// Only update the DOM if the visible range has changed
renderItems(startIndex, endIndex);
});
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* ## Monitorying network traffic for detecting unusual activity
* - an application that monitors network traffic and measures the amount of data transmitted over a network in each second
* - The goal is to detect if the network is under a heavy load by identifying the maximum amount of data transferred over any 5-second window.
* ### Problem
* - You have a stream of data representing the amount of traffic (in MB) transmitted per second
* - you want to find the maximum traffic in any 5-second window.
* ### Solution
* - use the sliding window pattern to sum up the traffic over 5 seconds,
* - then slide the window by one second at a time, keeping track of the maximum traffic in each 5-second period.
*/
export abstract class NetworkTrafficMonitoring {
/**
* Max Traffic in 5-second Window
* @param traffic - MB per second traffic oever 10 seconds
* @param windowSize - Monitor 5-second windows
*/
public static maxTrafficInWindow(
traffic: number[],
windowSize: number,
): number {
let maxTraffic = 0;
let currentWindowTraffic = 0;

// Initialize the window with the first `windowSize` seconds of traffic
for (let i = 0; i < windowSize; i++) {
currentWindowTraffic += traffic[i];
}

maxTraffic = currentWindowTraffic;

// Slide the window across the traffic data
for (let i = windowSize; i < traffic.length; i++) {
// Update the window by subtracting the outgoing traffic and adding the new incoming traffic
currentWindowTraffic += traffic[i] - traffic[i - windowSize];
maxTraffic = Math.max(maxTraffic, currentWindowTraffic);
}

return maxTraffic;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* ## A Pagination System that using the sliding window pattern
* - involves managing a "window" of items that can be shifted forward and backward as the user navigates between pages.
* - This is useful for applications where only a portion of the total data (a "window") needs to be displayed at a time.
* ### Approach
* - Window Size: This is the number of items displayed per page.
* - Sliding Window: The window slides forward or backward as the user navigates between pages.
* - Data Array: The total array of data remains the same, but the view of the data changes according to the window size.
*/
export class Paginator<T> {
private data: T[];
private windowSize: number;
private currentPage: number;

/**
* @param data - data array
* @param windowSize - window size
*/
constructor(data: T[], windowSize: number) {
this.data = data;
this.windowSize = windowSize;
this.currentPage = 0;
}

/** get current page items */
getCurrentPageItems(): T[] {
const start = this.currentPage * this.windowSize;
const end = start + this.windowSize;
return this.data.slice(start, end);
}

/** move to next page */
next(): void {
if (this.currentPage < Math.ceil(this.data.length / this.windowSize) - 1) {
this.currentPage++;
}
}

/** move to the previous page */
prev(): void {
if (this.currentPage > 0) {
this.currentPage--;
}
}

/** get total number of pages */
getTotalPages(): number {
return Math.ceil(this.data.length / this.windowSize);
}

/** get current page number (1-indexed for displayed) */
getCurrentPageNumber(): number {
return this.currentPage + 1;
}

/*** get item by specific index in data array */
getItemByIndex(index: number): T | null {
if (index >= 0 && index < this.data.length) {
return this.data[index];
}
return null;
}
}

// Example Usage
const items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; // Data to paginate
const paginator = new Paginator(items, 3); // Show 3 items per page

console.log('Page 1:', paginator.getCurrentPageItems()); // Output: [1, 2, 3]

paginator.next();
console.log('Page 2:', paginator.getCurrentPageItems()); // Output: [4, 5, 6]

paginator.next();
console.log('Page 3:', paginator.getCurrentPageItems()); // Output: [7, 8, 9]

paginator.next();
console.log('Page 4:', paginator.getCurrentPageItems()); // Output: [10, 11]

paginator.prev();
console.log('Page 3:', paginator.getCurrentPageItems()); // Output: [7, 8, 9]

console.log('Item by index: ', paginator.getItemByIndex(2));
console.log('Current Page:', paginator.getCurrentPageNumber());
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Logger } from '@nestjs/common';
import { SlidingWindowPattern } from '.';
import { NetworkTrafficMonitoring } from './network-traffic-monitoring';

export abstract class SlidingWindowPatternUsage {
private static logger = new Logger(SlidingWindowPatternUsage.name);
Expand All @@ -25,4 +26,14 @@ export abstract class SlidingWindowPatternUsage {
' // Output: 4 (substring "araa")',
);
}

public static maxTrafficInWindowUsage() {
const trafficData = [5, 1, 3, 7, 2, 6, 4, 8, 9, 3];
const windowSize = 5;
const result = NetworkTrafficMonitoring.maxTrafficInWindow(
trafficData,
windowSize,
);
this.logger.debug('maxTrafficInWindow usage -> ' + result);
}
}

0 comments on commit fe5f26d

Please sign in to comment.