Find the Punishment Number of an Integer

MEDIUM

Description

Given a positive integer n, return the punishment number of n.

The punishment number of n is defined as the sum of the squares of all integers i such that:

  • 1 <= i <= n
  • The decimal representation of i * i can be partitioned into contiguous substrings such that the sum of the integer values of these substrings equals i.

 

Example 1:

Input: n = 10
Output: 182
Explanation: There are exactly 3 integers i in the range [1, 10] that satisfy the conditions in the statement:
- 1 since 1 * 1 = 1
- 9 since 9 * 9 = 81 and 81 can be partitioned into 8 and 1 with a sum equal to 8 + 1 == 9.
- 10 since 10 * 10 = 100 and 100 can be partitioned into 10 and 0 with a sum equal to 10 + 0 == 10.
Hence, the punishment number of 10 is 1 + 81 + 100 = 182

Example 2:

Input: n = 37
Output: 1478
Explanation: There are exactly 4 integers i in the range [1, 37] that satisfy the conditions in the statement:
- 1 since 1 * 1 = 1. 
- 9 since 9 * 9 = 81 and 81 can be partitioned into 8 + 1. 
- 10 since 10 * 10 = 100 and 100 can be partitioned into 10 + 0. 
- 36 since 36 * 36 = 1296 and 1296 can be partitioned into 1 + 29 + 6.
Hence, the punishment number of 37 is 1 + 81 + 100 + 1296 = 1478

 

Constraints:

  • 1 <= n <= 1000

Approaches

Checkout 2 different approaches to solve Find the Punishment Number of an Integer. Click on different approaches to view the approach and algorithm in detail.

Brute-Force with Recursive Backtracking

This approach iterates through each integer i from 1 to n. For each i, it first calculates its square, i*i, and converts it into a string. Then, a recursive backtracking function is used to determine if this string can be partitioned into substrings whose integer values sum up to i. If a valid partition exists, i*i is added to a running total. This method directly translates the problem statement into code.

Algorithm

  • Initialize punishmentSum = 0.
  • For i from 1 to n:
    • Let s = String.valueOf(i * i).
    • If a helper function canPartition(s, i) returns true, add i * i to punishmentSum.
  • Return punishmentSum.
  • The canPartition function uses a recursive depth-first search (dfs) to check the condition.
  • dfs(s, target, index, currentSum) function:
    • Base Case: If index reaches the end of the string s, it means we have processed the entire string. Return true if currentSum equals target, otherwise false.
    • Recursive Step: Iterate through all possible next substrings starting from index. For each substring:
      • Parse it to an integer num.
      • If currentSum + num exceeds target, we can prune this path and all subsequent paths from this index because numbers will only get larger.
      • Make a recursive call dfs(s, target, j + 1, currentSum + num) for the rest of the string.
      • If any recursive call returns true, it means a valid partition is found, so propagate true up the call stack.
    • If the loop completes without finding a valid partition, return false.

The main function punishmentNumber(n) initializes a sum to zero and then loops from i = 1 to n. Inside the loop, it calculates square = i * i and converts it to a String s. It then calls a helper function, canPartition(s, i), to check if s can be partitioned to sum to i. If canPartition returns true, square is added to the sum.

The canPartition function itself is a wrapper that initiates a recursive search. It calls a backtracking function dfs(s, target, index, currentSum) which explores all possible partitions of the string s starting from a given index to see if they can sum up to the target.

class Solution {
    public int punishmentNumber(int n) {
        int totalPunishment = 0;
        for (int i = 1; i <= n; i++) {
            String s = String.valueOf(i * i);
            if (canPartition(s, i)) {
                totalPunishment += i * i;
            }
        }
        return totalPunishment;
    }

    private boolean canPartition(String s, int target) {
        return dfs(s, target, 0, 0);
    }

    private boolean dfs(String s, int target, int index, int currentSum) {
        if (index == s.length()) {
            return currentSum == target;
        }

        for (int j = index; j < s.length(); j++) {
            String sub = s.substring(index, j + 1);
            int num = Integer.parseInt(sub);

            if (currentSum + num > target) {
                // Optimization: if current sum already exceeds target,
                // no need to check longer numbers from this index.
                break;
            }

            if (dfs(s, target, j + 1, currentSum + num)) {
                return true;
            }
        }

        return false;
    }
}

Complexity Analysis

Time Complexity: O(N * K), where `N` is the input `n`, and `K` is the cost of the `canPartition` check. The `dfs` function's complexity is exponential in the length of the string `s`, let's say `L`. `L = O(log(i^2)) = O(log i)`. The number of partitions of a string of length `L` is `2^(L-1)`. So, `K` is roughly `O(2^L)`. Given `N <= 1000`, `L` is at most 7, so this is feasible.Space Complexity: O(log N). The space complexity is determined by the maximum depth of the recursion stack for the `dfs` function. The depth is at most the length of the string representation of `i*i`, which is proportional to `log(i^2)` or `log N`.

Pros and Cons

Pros:
  • Conceptually simple and a direct implementation of the problem requirements.
  • Does not require complex data structures.
Cons:
  • Can be slow due to the exponential nature of the recursive partition check, especially for larger values of n (though feasible for the given constraints).
  • For multiple test cases (as in a competitive programming platform), it recomputes the same results for smaller n values repeatedly.

Code Solutions

Checking out 3 solutions in different languages for Find the Punishment Number of an Integer. Click on different languages to view the code.


Video Solution

Watch the video walkthrough for Find the Punishment Number of an Integer



Patterns:

MathBacktracking

Subscribe to Scale Engineer newsletter

Learn about System Design, Software Engineering, and interview experiences every week.

No spam, unsubscribe at any time.