Minimum Operations to Make a Special Number
MedPrompt
You are given a 0-indexed string num representing a non-negative integer.
In one operation, you can pick any digit of num and delete it. Note that if you delete all the digits of num, num becomes 0.
Return the minimum number of operations required to make num special.
An integer x is considered special if it is divisible by 25.
Example 1:
Input: num = "2245047"
Output: 2
Explanation: Delete digits num[5] and num[6]. The resulting number is "22450" which is special since it is divisible by 25.
It can be shown that 2 is the minimum number of operations required to get a special number.Example 2:
Input: num = "2908305"
Output: 3
Explanation: Delete digits num[3], num[4], and num[6]. The resulting number is "2900" which is special since it is divisible by 25.
It can be shown that 3 is the minimum number of operations required to get a special number.Example 3:
Input: num = "10"
Output: 1
Explanation: Delete digit num[0]. The resulting number is "0" which is special since it is divisible by 25.
It can be shown that 1 is the minimum number of operations required to get a special number.
Constraints:
1 <= num.length <= 100numonly consists of digits'0'through'9'.numdoes not contain any leading zeros.
Approaches
2 approaches with complexity analysis and trade-offs.
This approach iterates through all possible pairs of indices (i, j) with i < j in the input string num. For each pair, it checks if the two digits num[i] and num[j] can form the last two digits of a special number (i.e., a number divisible by 25). If they can, it calculates the number of deletions required and updates the minimum found so far. The special case of forming the number '0' is also handled as a baseline.
Algorithm
-
- Get the length
nof the stringnum.
- Get the length
-
- Initialize a variable
minOpston. Ifnumcontains '0', updateminOpston-1. This handles the base case of forming the number 0.
- Initialize a variable
-
- Use a nested loop. The outer loop iterates with index
ifrom0ton-1.
- Use a nested loop. The outer loop iterates with index
-
- The inner loop iterates with index
jfromi+1ton-1.
- The inner loop iterates with index
-
- Inside the inner loop, form a two-digit number using the characters
num.charAt(i)andnum.charAt(j).
- Inside the inner loop, form a two-digit number using the characters
-
- Check if this two-digit number is divisible by 25 (i.e., it's 0, 25, 50, or 75).
-
- If it is, a valid subsequence ending is found. The number of deletions required is the count of characters between indices
iandj, plus the count of characters after indexj. This is calculated as(j - i - 1) + (n - 1 - j).
- If it is, a valid subsequence ending is found. The number of deletions required is the count of characters between indices
-
- Update
minOpswith the minimum value found so far.
- Update
-
- After the loops complete, return
minOps.
- After the loops complete, return
Walkthrough
A number is considered special if it's divisible by 25. This implies that the number must end in "00", "25", "50", "75", or it could be the number "0" itself.
This brute-force method systematically explores all possibilities for the last two digits. We initialize the minimum operations minOps by considering the simplest special number, "0". If the input string num contains a '0', we can achieve this by deleting all other n-1 characters. If not, we'd have to delete all n characters.
Next, we use nested loops to examine every pair of characters (num[i], num[j]) where i < j. This pair represents a potential two-digit ending for our special number. For each pair, we form the two-digit number and check if it's one of 0, 25, 50, or 75. If it is, we've found a valid subsequence. The number of characters to delete are those between index i and j, and all characters after index j. The count of characters to delete is (j - i - 1) (between i and j) plus (n - 1 - j) (after j). We keep track of the minimum deletions found across all valid pairs and return this minimum value.
class Solution { public int minimumOperations(String num) { int n = num.length(); int minOps = n; // Case: delete all digits to get 0 boolean hasZero = false; for (int i = 0; i < n; i++) { if (num.charAt(i) == '0') { hasZero = true; break; } } if (hasZero) { minOps = n - 1; // Case: keep one '0' } for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { int firstDigit = num.charAt(i) - '0'; int secondDigit = num.charAt(j) - '0'; int lastTwoDigits = firstDigit * 10 + secondDigit; if (lastTwoDigits % 25 == 0) { // Deletions: characters between i and j, and after j int deletions = (j - i - 1) + (n - 1 - j); minOps = Math.min(minOps, deletions); } } } return minOps; }}Complexity
Time
O(n^2), where n is the length of the input string `num`. The nested loops iterate through all possible pairs of indices, which is the dominant factor in the runtime.
Space
O(1), as we only use a few variables to store state, regardless of the input size.
Trade-offs
Pros
Simple to understand and implement.
Correctly solves the problem by exhaustively checking all valid two-digit endings.
Cons
Inefficient for large strings due to its quadratic time complexity, which might be too slow if the constraints were larger.
Solutions
Solution
class Solution {private Integer[][] f;private String num;private int n;public int minimumOperations(String num) { n = num.length(); this.num = num; f = new Integer[n][25]; return dfs(0, 0); }private int dfs(int i, int k) { if (i == n) { return k == 0 ? 0 : n; } if (f[i][k] != null) { return f[i][k]; } f[i][k] = dfs(i + 1, k) + 1; f[i][k] = Math.min(f[i][k], dfs(i + 1, (k * 10 + num.charAt(i) - '0') % 25)); return f[i][k]; }}Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.