Given a number N, we have to find the minimum number of palindromes required to express N as a sum of them. Examples:
Input: N = 11 Output: 1 11 is itself a palindrome. Input: N = 65 Output: 3 65 can be expressed as a sum of three palindromes (55, 9, 1).
Approach: We can use Dynamic Programming to solve this problem. The idea is to first generate all the palindromes up to N in a sorted fashion, and then we can treat this problem as a variation of the subset sum problem, where we have to find the size of the smallest subset such that its sum is N.
Below is the implementation of above approach:
CPP
#include <bits/stdc++.h>
using namespace std;
vector<vector< long long > > dp;
int createPalindrome( int input, bool isOdd)
{
int n = input;
int palin = input;
if (isOdd)
n /= 10;
while (n > 0) {
palin = palin * 10 + (n % 10);
n /= 10;
}
return palin;
}
vector< int > generatePalindromes( int N)
{
vector< int > palindromes;
int number;
for ( int j = 0; j < 2; j++) {
int i = 1;
while ((number = createPalindrome(i++, j)) <= N)
palindromes.push_back(number);
}
return palindromes;
}
long long minimumSubsetSize(vector< int >& A, int i, int j, int N)
{
if (!N)
return 0;
if (i > j || A[i] > N)
return INT_MAX;
if (dp[i][N])
return dp[i][N];
dp[i][N] = min(1 + minimumSubsetSize(A, i + 1, j,
N - A[i]),
minimumSubsetSize(A, i + 1, j, N));
return dp[i][N];
}
int minimumNoOfPalindromes( int N)
{
vector< int > palindromes = generatePalindromes(N);
sort(palindromes.begin(), palindromes.end());
dp = vector<vector< long long > >(palindromes.size(),
vector< long long >(N + 1, 0));
return minimumSubsetSize(palindromes, 0,
palindromes.size() - 1, N);
}
int main()
{
int N = 65;
cout << minimumNoOfPalindromes(N);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
static long [][] dp;
static int createPalindrome( int input, int isOdd)
{
int n = input;
int palin = input;
if (isOdd > 0 )
n /= 10 ;
while (n > 0 ) {
palin = palin * 10 + (n % 10 );
n /= 10 ;
}
return palin;
}
static ArrayList<Integer> generatePalindromes( int N)
{
ArrayList<Integer> palindromes = new ArrayList<>();
int number;
for ( int j = 0 ; j < 2 ; j++) {
int i = 1 ;
while ((number = createPalindrome(i++, j)) <= N)
palindromes.add(number);
}
return palindromes;
}
static long minimumSubsetSize(ArrayList<Integer> A, int i, int j, int N)
{
if (N == 0 )
return 0 ;
if (i > j || A.get(i) > N)
return Integer.MAX_VALUE;
if (dp[i][N] > 0 )
return dp[i][N];
dp[i][N] = Math.min( 1 + minimumSubsetSize(A, i + 1 , j,
N - A.get(i)),
minimumSubsetSize(A, i + 1 , j, N));
return dp[i][N];
}
static int minimumNoOfPalindromes( int N)
{
ArrayList<Integer> palindromes = generatePalindromes(N);
Collections.sort(palindromes);
dp = new long [palindromes.size()][N + 1 ];
return ( int )minimumSubsetSize(palindromes, 0 ,
palindromes.size() - 1 , N);
}
public static void main(String args[])
{
int N = 65 ;
System.out.println(minimumNoOfPalindromes(N));
}
}
|
Python3
dp = [[ 0 for i in range ( 1000 )] for i in range ( 1000 )]
def createPalindrome( input , isOdd):
n = input
palin = input
if (isOdd):
n / / = 10
while (n > 0 ):
palin = palin * 10 + (n % 10 )
n / / = 10
return palin
def generatePalindromes(N):
palindromes = []
number = 0
for j in range ( 2 ):
i = 1
number = createPalindrome(i, j)
while number < = N:
number = createPalindrome(i, j)
palindromes.append(number)
i + = 1
return palindromes
def minimumSubsetSize(A, i, j, N):
if ( not N):
return 0
if (i > j or A[i] > N):
return 10 * * 9
if (dp[i][N]):
return dp[i][N]
dp[i][N] = min ( 1 + minimumSubsetSize(A, i + 1 , j, N - A[i]),
minimumSubsetSize(A, i + 1 , j, N))
return dp[i][N]
def minimumNoOfPalindromes(N):
palindromes = generatePalindromes(N)
palindromes = sorted (palindromes)
return minimumSubsetSize(palindromes, 0 , len (palindromes) - 1 , N)
N = 65
print (minimumNoOfPalindromes(N))
|
C#
using System;
using System.Collections.Generic;
class GFG {
static long [, ] dp;
static int createPalindrome( int input, int isOdd)
{
int n = input;
int palin = input;
if (isOdd > 0)
n /= 10;
while (n > 0) {
palin = palin * 10 + (n % 10);
n /= 10;
}
return palin;
}
static List< int > generatePalindromes( int N)
{
List< int > palindromes = new List< int >();
int number;
for ( int j = 0; j < 2; j++) {
int i = 1;
while ((number = createPalindrome(i++, j)) <= N)
palindromes.Add(number);
}
return palindromes;
}
static long minimumSubsetSize(List< int > A, int i, int j,
int N)
{
if (N == 0)
return 0;
if (i > j || A[i] > N)
return Int32.MaxValue;
if (dp[i, N] > 0)
return dp[i, N];
dp[i, N] = Math.Min(
1 + minimumSubsetSize(A, i + 1, j, N - A[i]),
minimumSubsetSize(A, i + 1, j, N));
return dp[i, N];
}
static int minimumNoOfPalindromes( int N)
{
List< int > palindromes = generatePalindromes(N);
palindromes.Sort();
dp = new long [palindromes.Count, N + 1];
return ( int )minimumSubsetSize(
palindromes, 0, palindromes.Count - 1, N);
}
public static void Main( string [] args)
{
int N = 65;
Console.WriteLine(minimumNoOfPalindromes(N));
}
}
|
Javascript
<script>
let dp = new Array(1000);
for (let i = 0; i < 1000; i++)
{
dp[i] = new Array(1000).fill(0);
}
function createPalindrome(input, isOdd){
let n = input
let palin = input
if (isOdd)
n = Math.floor(n /10)
while (n > 0){
palin = palin * 10 + (n % 10)
n = Math.floor(n /10)
}
return palin
}
function generatePalindromes(N){
let palindromes = []
let number = 0
for (let j = 0; j < 2; j++)
{
let i = 1
number = createPalindrome(i, j)
while (number <= N){
number = createPalindrome(i, j)
palindromes.push(number)
i += 1
}
}
return palindromes
}
function minimumSubsetSize(A, i, j, N){
if (N == 0)
return 0
if (i > j || A[i] > N)
return Math.pow(10,9)
if (dp[i][N])
return dp[i][N]
dp[i][N] = Math.min(1 + minimumSubsetSize(A, i + 1, j, N - A[i]),
minimumSubsetSize(A, i + 1, j, N))
return dp[i][N]
}
function minimumNoOfPalindromes(N){
let palindromes = generatePalindromes(N)
palindromes.sort((a,b)=>a-b)
return minimumSubsetSize(palindromes, 0, palindromes.length - 1, N)
}
let N = 65
document.write(minimumNoOfPalindromes(N), "</br>" )
</script>
|
Efficient approach : Using DP Tabulation method ( Iterative approach )
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
vector<vector< long long >> dp;
int createPalindrome( int input, bool isOdd) {
int n = input;
int palin = input;
if (isOdd)
n /= 10;
while (n > 0) {
palin = palin * 10 + (n % 10);
n /= 10;
}
return palin;
}
vector< int > generatePalindromes( int N) {
vector< int > palindromes;
int number;
for ( int j = 0; j < 2; j++) {
int i = 1;
while ((number = createPalindrome(i++, j)) <= N)
palindromes.push_back(number);
}
return palindromes;
}
long long minimumSubsetSize(vector< int >& A, int N) {
int n = A.size();
dp = vector<vector< long long >>(n + 1, vector< long long >(N + 1, 0));
for ( int i = 0; i <= n; i++)
dp[i][0] = 0;
for ( int j = 1; j <= N; j++)
dp[0][j] = INT_MAX;
for ( int i = 1; i <= n; i++) {
for ( int j = 1; j <= N; j++) {
if (A[i - 1] > j)
dp[i][j] = dp[i - 1][j];
else
dp[i][j] = min(1 + dp[i - 1][j - A[i - 1]], dp[i - 1][j]);
}
}
return dp[n][N];
}
int minimumNoOfPalindromes( int N) {
vector< int > palindromes = generatePalindromes(N);
sort(palindromes.begin(), palindromes.end());
return minimumSubsetSize(palindromes, N);
}
int main() {
int N = 65;
cout << minimumNoOfPalindromes(N);
return 0;
}
|
Java
import java.util.HashMap;
import java.util.Map;
public class MinimumPalindromes {
static Map<Long, Long> memo = new HashMap<>();
static long createPalindrome( long input, boolean isOdd) {
long n = input;
long palin = input;
if (isOdd)
n /= 10 ;
while (n > 0 ) {
palin = palin * 10 + (n % 10 );
n /= 10 ;
}
return palin;
}
static long minimumNumberOfPalindromes( long N) {
if (N == 0 ) {
return 0 ;
}
if (memo.containsKey(N)) {
return memo.get(N);
}
long result = Long.MAX_VALUE;
for ( int i = 1 ; ; i++) {
long palindrome = createPalindrome(i, true );
if (palindrome <= N) {
result = Math.min(result, 1 + minimumNumberOfPalindromes(N - palindrome));
} else {
break ;
}
}
for ( int i = 1 ; ; i++) {
long palindrome = createPalindrome(i, false );
if (palindrome <= N) {
result = Math.min(result, 1 + minimumNumberOfPalindromes(N - palindrome));
} else {
break ;
}
}
memo.put(N, result);
return result;
}
public static void main(String[] args) {
long N = 65 ;
System.out.println(minimumNumberOfPalindromes(N));
}
}
|
Python3
dp = []
def create_palindrome(input_num, is_odd):
num = input_num
palindrome = input_num
if is_odd:
num / / = 10
while num > 0 :
palindrome = palindrome * 10 + (num % 10 )
num / / = 10
return palindrome
def generate_palindromes(N):
palindromes = []
for j in range ( 2 ):
i = 1
while True :
number = create_palindrome(i, j)
if number < = N:
palindromes.append(number)
i + = 1
else :
break
return palindromes
def minimum_subset_size(A, N):
n = len (A)
dp = [[ 0 ] * (N + 1 ) for _ in range (n + 1 )]
for i in range (n + 1 ):
dp[i][ 0 ] = 0
for j in range ( 1 , N + 1 ):
dp[ 0 ][j] = 10 * * 18
for i in range ( 1 , n + 1 ):
for j in range ( 1 , N + 1 ):
if A[i - 1 ] > j:
dp[i][j] = dp[i - 1 ][j]
else :
dp[i][j] = min ( 1 + dp[i - 1 ][j - A[i - 1 ]], dp[i - 1 ][j])
return dp[n][N]
def minimum_no_of_palindromes(N):
palindromes = generate_palindromes(N)
palindromes.sort()
return minimum_subset_size(palindromes, N)
if __name__ = = "__main__" :
N = 65
print (minimum_no_of_palindromes(N))
|
C#
using System;
using System.Collections.Generic;
public class MinimumPalindromes
{
static List<List< long >> dp;
static long CreatePalindrome( long input, bool isOdd)
{
long n = input;
long palin = input;
if (isOdd)
n /= 10;
while (n > 0)
{
palin = palin * 10 + (n % 10);
n /= 10;
}
return palin;
}
static List< long > GeneratePalindromes( long N)
{
List< long > palindromes = new List< long >();
long number;
for ( int j = 0; j < 2; j++)
{
long i = 1;
while ((number = CreatePalindrome(i++, j == 0)) <= N)
palindromes.Add(number);
}
return palindromes;
}
static long MinimumSubsetSize(List< long > A, long N)
{
int n = A.Count;
dp = new List<List< long >>(n + 1);
for ( int i = 0; i <= n; i++)
dp.Add( new List< long >( new long [N + 1]));
for ( int i = 0; i <= n; i++)
dp[i][0] = 0;
for ( int j = 1; j <= N; j++)
dp[0][j] = int .MaxValue;
for ( int i = 1; i <= n; i++)
{
for ( int j = 1; j <= N; j++)
{
if (A[i - 1] > j)
dp[i][j] = dp[i - 1][j];
else
dp[i][j] = Math.Min(1 + dp[i - 1][j - ( int )A[i - 1]], dp[i - 1][j]);
}
}
return dp[n][( int )N];
}
static long MinimumNumberOfPalindromes( long N)
{
List< long > palindromes = GeneratePalindromes(N);
palindromes.Sort();
return MinimumSubsetSize(palindromes, N);
}
public static void Main( string [] args)
{
long N = 65;
Console.WriteLine(MinimumNumberOfPalindromes(N));
}
}
|
Javascript
function createPalindrome(input, isOdd) {
let n = input;
let palin = input;
if (isOdd)
n = Math.floor(n / 10);
while (n > 0) {
palin = palin * 10 + (n % 10);
n = Math.floor(n / 10);
}
return palin;
}
function generatePalindromes(N) {
const palindromes = [];
let number;
for (let j = 0; j < 2; j++) {
let i = 1;
while ((number = createPalindrome(i++, j)) <= N)
palindromes.push(number);
}
return palindromes;
}
function minimumSubsetSize(A, N) {
const n = A.length;
const dp = new Array(n + 1);
for (let i = 0; i <= n; i++) {
dp[i] = new Array(N + 1).fill(0);
}
for (let i = 0; i <= n; i++) {
dp[i][0] = 0;
}
for (let j = 1; j <= N; j++) {
dp[0][j] = Number.MAX_VALUE;
}
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= N; j++) {
if (A[i - 1] > j) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = Math.min(1 + dp[i - 1][j - A[i - 1]], dp[i - 1][j]);
}
}
}
return dp[n][N];
}
function minimumNoOfPalindromes(N) {
const palindromes = generatePalindromes(N);
palindromes.sort((a, b) => a - b);
return minimumSubsetSize(palindromes, N);
}
const N = 65;
console.log(minimumNoOfPalindromes(N));
|
Time Complexity: O(N*M) Auxiliary Space: O(N*M)
|