Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Evaluating Reverse Polish Notation and Implementing Sliding Window Max and Top K Frequent Elements Using Stacks and Queues

Tech 1

Reverse Polish Notation (RPN), or postfix notation, is evaluated using a stack data structure. The algorithm iterates through an array of tokens. When a numeric token is encountered, it is pushed onto the stack. Upon encountering an operator (+, -, *, /), the two most recent numbers are popped from the stack. The operation is performed with these numbers (the second popped operand is the left-hand side of the operation), and the result is pushed back onto the stack. The process continues until all tokens are processed, leaving the final result as the sole element in the stack.

function computeRPN(tokens) {
    const calcStack = [];
    const operators = new Set(['+', '-', '*', '/']);
    
    for (const token of tokens) {
        if (operators.has(token)) {
            const rightOperand = calcStack.pop();
            const leftOperand = calcStack.pop();
            
            let computationResult;
            if (token === '+') computationResult = leftOperand + rightOperand;
            else if (token === '-') computationResult = leftOperand - rightOperand;
            else if (token === '*') computationResult = leftOperand * rightOperand;
            else if (token === '/') computationResult = Math.trunc(leftOperand / rightOperand);
            
            calcStack.push(computationResult);
        } else {
            calcStack.push(parseInt(token, 10));
        }
    }
    return calcStack.pop();
}

For the sliding window maximum problem, a monotonic decreasing queue can be used to efficiently track the maximum value within a window of size k as it moves across an array. The queue's front always contains the current window's maximum. When adding a new element (enqueue), any elements in the queue smaller than the new element are removed from the back, ensuring the decreasing order. When removing an element (dequeue), it is only removed from the front if it matches the element exiting the window.

function findWindowMaxima(arr, windowSize) {
    class MonotonicQueue {
        constructor() {
            this.items = [];
        }
        
        addElement(val) {
            while (this.items.length > 0 && this.items[this.items.length - 1] < val) {
                this.items.pop();
            }
            this.items.push(val);
        }
        
        removeElement(val) {
            if (this.items.length > 0 && this.items[0] === val) {
                this.items.shift();
            }
        }
        
        getMax() {
            return this.items[0];
        }
    }
    
    const mq = new MonotonicQueue();
    const result = [];
    let startIdx = 0;
    
    // Initialize the first window
    for (let i = 0; i < windowSize; i++) {
        mq.addElement(arr[i]);
    }
    result.push(mq.getMax());
    
    // Slide the window
    for (let endIdx = windowSize; endIdx < arr.length; endIdx++) {
        mq.addElement(arr[endIdx]);
        mq.removeElement(arr[startIdx]);
        result.push(mq.getMax());
        startIdx++;
    }
    
    return result;
}

To find the top K frequent elements, a min-heap (priority queue) is effective. First, a hash map counts the frequency of each element. Then, a min-heap of size k is maintained, where the priority is based on frequency. Elements are inserted into the heap; if the heap size exceeds k, the element with the smallest frequency (the root of the min-heap) is removed. This ensures the heap always contains the k most frequent elements encountered so far.

function getMostFrequent(nums, k) {
    const frequencyMap = new Map();
    for (const num of nums) {
        frequencyMap.set(num, (frequencyMap.get(num) || 0) + 1);
    }
    
    // Assuming a PriorityQueue implementation is available with a comparator for a min-heap.
    const minHeap = new PriorityQueue((a, b) => a.freq - b.freq);
    
    for (const [element, freq] of frequencyMap) {
        minHeap.enqueue({ val: element, freq: freq });
        if (minHeap.size() > k) {
            minHeap.dequeue(); // Removes the element with the smallest frequency
        }
    }
    
    const topK = [];
    while (minHeap.size() > 0) {
        topK.push(minHeap.dequeue().val);
    }
    return topK;
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.