Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1694. Reformat Phone Number - Leetcode Solution

Problem Description

Given a string number representing a phone number, reformat it so that the digits are grouped and separated by dashes '-' according to the following rules:

  • Remove all spaces and dashes from the input string.
  • Group the digits in blocks of 3 from left to right.
  • If the last group has 4 digits, split it into two groups of 2 digits each (i.e., "22-22").
  • If the last group has 2 or 3 digits, leave them as is.
  • Return the reformatted phone number as a string.

Constraints:

  • There is always at least 2 digits in the input.
  • All groups must be separated by a single dash '-'.
  • There is only one valid solution for each input.

Thought Process

The problem asks us to reformat a phone number string by grouping digits and adding dashes according to specific rules. At first, the brute-force approach would be to process the input character by character, grouping them into sets of three, and handling the special cases at the end. However, upon closer inspection, we realize that:

  • Spaces and dashes are irrelevant and can be removed right away.
  • The main challenge is handling the last few digits, especially if there are 4 digits left (which should be split into two groups of 2).
  • We want an efficient solution that processes the string in a single pass, or at most two passes, without excessive string manipulation.

By focusing on removing non-digit characters first, and then grouping the digits, we can simplify the implementation and make the solution more readable and efficient.

Solution Approach

Let's break down the steps to solve the problem:

  1. Clean the Input:
    • Remove all spaces and dashes from the input string, leaving only digits.
  2. Group the Digits:
    • Iterate through the cleaned digit string, appending groups of 3 digits to a result list.
    • When there are 4 digits left, split them into two groups of 2 digits.
    • If 2 or 3 digits remain at the end, group them as is.
  3. Join the Groups:
    • Combine the groups into a single string, separated by dashes.

This approach ensures that we only process the string a couple of times (once to clean and once to group), and we handle the special cases for the last few digits as required by the problem statement.

Example Walkthrough

Let's walk through an example with the input: number = "1-23-45 6"

  1. Step 1: Clean the Input
    Remove spaces and dashes: 123456
  2. Step 2: Group the Digits
    The cleaned string has 6 digits.
    - Take the first 3 digits: 123
    - 3 digits left: 456
  3. Step 3: Join the Groups
    Combine them with dashes: 123-456

Another example: number = "123 4-567"

  • Cleaned: 1234567
  • First group: 123
  • Second group: 456
  • 1 digit left: 7, but since the last group cannot be a single digit, we should have stopped before and split the last 4 digits into two groups of 2: 12-34-56-7 is invalid. Instead, we do: 123-45-67

Code Implementation

class Solution:
    def reformatNumber(self, number: str) -> str:
        digits = [c for c in number if c.isdigit()]
        res = []
        i = 0
        n = len(digits)
        while n - i > 4:
            res.append(''.join(digits[i:i+3]))
            i += 3
        if n - i == 4:
            res.append(''.join(digits[i:i+2]))
            res.append(''.join(digits[i+2:i+4]))
        else:
            res.append(''.join(digits[i:]))
        return '-'.join(res)
      
class Solution {
public:
    string reformatNumber(string number) {
        string digits;
        for (char c : number)
            if (isdigit(c))
                digits += c;
        vector<string> res;
        int i = 0, n = digits.size();
        while (n - i > 4) {
            res.push_back(digits.substr(i, 3));
            i += 3;
        }
        if (n - i == 4) {
            res.push_back(digits.substr(i, 2));
            res.push_back(digits.substr(i + 2, 2));
        } else {
            res.push_back(digits.substr(i));
        }
        string ans = res[0];
        for (int j = 1; j < res.size(); ++j)
            ans += "-" + res[j];
        return ans;
    }
};
      
class Solution {
    public String reformatNumber(String number) {
        StringBuilder digits = new StringBuilder();
        for (char c : number.toCharArray()) {
            if (Character.isDigit(c)) {
                digits.append(c);
            }
        }
        List<String> res = new ArrayList<>();
        int i = 0, n = digits.length();
        while (n - i > 4) {
            res.add(digits.substring(i, i + 3));
            i += 3;
        }
        if (n - i == 4) {
            res.add(digits.substring(i, i + 2));
            res.add(digits.substring(i + 2, i + 4));
        } else {
            res.add(digits.substring(i, n));
        }
        return String.join("-", res);
    }
}
      
var reformatNumber = function(number) {
    let digits = [];
    for (let c of number) {
        if (c >= '0' && c <= '9') digits.push(c);
    }
    let res = [];
    let i = 0, n = digits.length;
    while (n - i > 4) {
        res.push(digits.slice(i, i + 3).join(''));
        i += 3;
    }
    if (n - i === 4) {
        res.push(digits.slice(i, i + 2).join(''));
        res.push(digits.slice(i + 2, i + 4).join(''));
    } else {
        res.push(digits.slice(i).join(''));
    }
    return res.join('-');
};
      

Time and Space Complexity

Brute-force approach: If we tried to generate all possible groupings and check which one matches the rules, the time complexity would be much higher and unnecessary.

Optimized approach (as above):

  • Time Complexity: O(n), where n is the length of the input string. We traverse the string once to filter digits, and once to group them.
  • Space Complexity: O(n), as we store the digits and the resulting groups.
The solution is efficient because each character is processed a constant number of times, and all operations (slicing, joining) are linear in the number of digits.

Summary

To solve the Reformat Phone Number problem, we first remove all non-digit characters, then group the digits according to the rules (mainly handling the special case for 4 digits at the end), and finally join the groups with dashes. The solution is straightforward, efficient, and only requires a couple of passes through the data. The key insight is to handle the grouping from left to right and pay special attention to the last few digits. This approach is both readable and optimal for the given constraints.