Problem

Let’s say a positive integer is a super-palindrome if it is a palindrome, and it is also the square of a palindrome.

Given two positive integers left and right represented as strings, return the number ofsuper-palindromes integers in the inclusive range [left, right].

Examples

Example 1

1
2
3
4
Input: left = "4", right = "1000"
Output: 4
**Explanation** : 4, 9, 121, and 484 are superpalindromes.
Note that 676 is not a superpalindrome: 26 * 26 = 676, but 26 is not a palindrome.

Example 2

1
2
Input: left = "1", right = "2"
Output: 1

Constraints

  • 1 <= left.length, right.length <= 18
  • left and right consist of only digits.
  • left and right cannot have leading zeros.
  • left and right represent integers in the range [1, 1018 - 1].
  • left is less than or equal to right.

Solution

Approach

We generate all palindromic numbers up to the square root of right, square them, and check if the result is a palindrome and within the range. We check both odd and even length palindromes.

Code

C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
public:
    bool isPalindrome(long long x) {
        string s = to_string(x);
        int l = 0, r = s.size() - 1;
        while (l < r) if (s[l++] != s[r--]) return false;
        return true;
    }
    int superpalindromesInRange(string left, string right) {
        long long l = stoll(left), r = stoll(right), ans = 0;
        // Odd length palindromes
        for (int k = 1; k < 100000; ++k) {
            string s = to_string(k), t = s;
            reverse(t.begin(), t.end() - 1);
            string pal = s + t.substr(1);
            long long v = stoll(pal);
            long long sq = v * v;
            if (sq > r) break;
            if (sq >= l && isPalindrome(sq)) ++ans;
        }
        // Even length palindromes
        for (int k = 1; k < 100000; ++k) {
            string s = to_string(k), t = s;
            reverse(t.begin(), t.end());
            string pal = s + t;
            long long v = stoll(pal);
            long long sq = v * v;
            if (sq > r) break;
            if (sq >= l && isPalindrome(sq)) ++ans;
        }
        return ans;
    }
};
Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
    private boolean isPalindrome(long x) {
        String s = Long.toString(x);
        int l = 0, r = s.length() - 1;
        while (l < r) if (s.charAt(l++) != s.charAt(r--)) return false;
        return true;
    }
    public int superpalindromesInRange(String left, String right) {
        long l = Long.parseLong(left), r = Long.parseLong(right), ans = 0;
        // Odd length palindromes
        for (int k = 1; k < 100000; ++k) {
            String s = Integer.toString(k);
            StringBuilder t = new StringBuilder(s).reverse();
            String pal = s + t.substring(1);
            long v = Long.parseLong(pal);
            long sq = v * v;
            if (sq > r) break;
            if (sq >= l && isPalindrome(sq)) ++ans;
        }
        // Even length palindromes
        for (int k = 1; k < 100000; ++k) {
            String s = Integer.toString(k);
            StringBuilder t = new StringBuilder(s).reverse();
            String pal = s + t.toString();
            long v = Long.parseLong(pal);
            long sq = v * v;
            if (sq > r) break;
            if (sq >= l && isPalindrome(sq)) ++ans;
        }
        return (int)ans;
    }
}
Kotlin
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
    private fun isPalindrome(x: Long): Boolean {
        val s = x.toString()
        return s == s.reversed()
    }
    fun superpalindromesInRange(left: String, right: String): Int {
        val l = left.toLong()
        val r = right.toLong()
        var ans = 0
        for (k in 1 until 100000) {
            val s = k.toString()
            val pal1 = (s + s.dropLast(1).reversed()).toLong()
            val sq1 = pal1 * pal1
            if (sq1 > r) break
            if (sq1 >= l && isPalindrome(sq1)) ans++
        }
        for (k in 1 until 100000) {
            val s = k.toString()
            val pal2 = (s + s.reversed()).toLong()
            val sq2 = pal2 * pal2
            if (sq2 > r) break
            if (sq2 >= l && isPalindrome(sq2)) ans++
        }
        return ans
    }
}
Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
    def superpalindromesInRange(self, left: str, right: str) -> int:
        l, r = int(left), int(right)
        ans = 0
        # Odd length palindromes
        for k in range(1, 100000):
            s = str(k)
            pal = int(s + s[-2::-1])
            sq = pal * pal
            if sq > r: break
            if sq >= l and str(sq) == str(sq)[::-1]:
                ans += 1
        # Even length palindromes
        for k in range(1, 100000):
            s = str(k)
            pal = int(s + s[::-1])
            sq = pal * pal
            if sq > r: break
            if sq >= l and str(sq) == str(sq)[::-1]:
                ans += 1
        return ans
Rust
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
impl Solution {
    pub fn superpalindromes_in_range(left: String, right: String) -> i32 {
        let l = left.parse::<u64>().unwrap();
        let r = right.parse::<u64>().unwrap();
        let mut ans = 0;
        for k in 1..100_000 {
            let s = k.to_string();
            let pal1 = format!("{}{}", s, s.chars().rev().skip(1).collect::<String>());
            let v1 = pal1.parse::<u64>().unwrap();
            let sq1 = v1 * v1;
            if sq1 > r { break; }
            if sq1 >= l && sq1.to_string() == sq1.to_string().chars().rev().collect::<String>() {
                ans += 1;
            }
        }
        for k in 1..100_000 {
            let s = k.to_string();
            let pal2 = format!("{}{}", s, s.chars().rev().collect::<String>());
            let v2 = pal2.parse::<u64>().unwrap();
            let sq2 = v2 * v2;
            if sq2 > r { break; }
            if sq2 >= l && sq2.to_string() == sq2.to_string().chars().rev().collect::<String>() {
                ans += 1;
            }
        }
        ans
    }
}
TypeScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
function superpalindromesInRange(left: string, right: string): number {
    const l = BigInt(left), r = BigInt(right);
    let ans = 0;
    for (let k = 1; k < 100000; ++k) {
        const s = k.toString();
        const pal1 = BigInt(s + s.slice(0, -1).split('').reverse().join(''));
        const sq1 = pal1 * pal1;
        if (sq1 > r) break;
        if (sq1 >= l && sq1.toString() === sq1.toString().split('').reverse().join('')) ans++;
    }
    for (let k = 1; k < 100000; ++k) {
        const s = k.toString();
        const pal2 = BigInt(s + s.split('').reverse().join(''));
        const sq2 = pal2 * pal2;
        if (sq2 > r) break;
        if (sq2 >= l && sq2.toString() === sq2.toString().split('').reverse().join('')) ans++;
    }
    return ans;
}

Explanation

We generate all palindromic numbers up to the square root of right, square them, and check if the result is a palindrome and within the range. Both odd and even length palindromes are considered.

Complexity

  • ⏰ Time complexity: O(N log N) where N is the number of palindromic roots generated (up to 2*10^5).
  • 🧺 Space complexity: O(1)