Smallest number after removing n digits in JavaScript

We need to write a JavaScript function that removes n digits from a number to make it as small as possible. This is a classic greedy algorithm problem that uses a stack-based approach.

Problem Statement

Given a number string m and an integer n, remove n digits from m to create the smallest possible number.

For example:

Input: m = '45456757', n = 3
Output: '44557'

We remove digits 5, 6, and 7 to get the smallest result.

Algorithm Approach

We use a greedy algorithm with a stack:

  • Process digits left to right (leftmost positions are most valuable)
  • Remove larger digits from the stack when a smaller digit appears
  • Keep the smallest possible digits in leftmost positions

Implementation

const m = '45456757';
const n = 3;

const removeDigits = (m, n, stack = []) => {
    let arr = m.split('').map(Number);
    
    for(let el of arr){
        // Remove larger digits from stack while we can
        while (n && stack.length && el < stack[stack.length - 1]){
            stack.pop();
            --n;
        };
        stack.push(el);
    };
    
    // Find first non-zero digit to avoid leading zeros
    let begin = stack.findIndex(el => el > 0);
    let end = stack.length - n;
    
    // Handle edge cases: empty result, all zeros, or invalid range
    return (!stack.length || begin == -1 || begin >= end) ? "0" : 
           stack.slice(begin, end).join('');
};

console.log(removeDigits(m, n));
44557

Step-by-Step Execution

For input '45456757' with n=3:

const traceExecution = (m, n) => {
    let stack = [];
    let arr = m.split('').map(Number);
    let removals = n;
    
    console.log('Processing digits:', arr);
    
    for(let i = 0; i < arr.length; i++){
        let el = arr[i];
        console.log(`\nProcessing digit: ${el}`);
        
        while (removals && stack.length && el < stack[stack.length - 1]){
            let removed = stack.pop();
            console.log(`  Removed ${removed} (${el} < ${removed})`);
            --removals;
        }
        
        stack.push(el);
        console.log(`  Stack now: [${stack.join(', ')}], removals left: ${removals}`);
    }
    
    return stack.slice(0, stack.length - removals).join('');
};

console.log('\nFinal result:', traceExecution('45456757', 3));
Processing digits: [ 4, 5, 4, 5, 6, 7, 5, 7 ]

Processing digit: 4
  Stack now: [4], removals left: 3

Processing digit: 5
  Stack now: [4, 5], removals left: 3

Processing digit: 4
  Removed 5 (4 < 5)
  Stack now: [4, 4], removals left: 2

Processing digit: 5
  Stack now: [4, 4, 5], removals left: 2

Processing digit: 6
  Stack now: [4, 4, 5, 6], removals left: 2

Processing digit: 7
  Stack now: [4, 4, 5, 6, 7], removals left: 2

Processing digit: 5
  Removed 7 (5 < 7)
  Removed 6 (5 < 6)
  Stack now: [4, 4, 5, 5], removals left: 0

Processing digit: 7
  Stack now: [4, 4, 5, 5, 7], removals left: 0

Final result: 44557

Edge Cases

// Test edge cases
console.log('Remove all digits:', removeDigits('123', 3));
console.log('Leading zeros:', removeDigits('10200', 1)); 
console.log('All same digits:', removeDigits('1111', 2));
Remove all digits: 0
Leading zeros: 200
All same digits: 11

Conclusion

This greedy algorithm efficiently finds the smallest number by maintaining smaller digits in more significant positions. The stack ensures we always keep the optimal digits while processing left to right.

Updated on: 2026-03-15T23:19:00+05:30

378 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements