Least Greater number with same digit sum

Given a number represented in the form of an array such that each element of the array stores a single digit of the number. That is, array for the number 1234 will be arr[] = {1,2,3,4}. The task is to find the least number greater than the given number but having the sum of digits equal to the given number.

For simplicity: Consider the length of number can be 20 at maximum.

Examples:

Input : arr[] = {0, 0, 0, 0, 0, 0, 0, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8 };
Output : 00000004799999999999
Explanation : Sum of digits = 110

Input : arr[] = {0, 0, 0, 0, 0, 0, 0, 3, 9, 7, 0, 0, 2, 9, 8, 9, 5, 9, 9, 0};
Output : 00000003970029896089
Explanation : Sum of digits = 70

A Brute Force Approach is to:

  1. Start from that number and increment the number by one.
  2. Check the sum. If the sum is same the return the number.
  3. Else return to step one.

A Better Approach is to jump to the next number in O(n) time complexity, where n is the length of string.

We divide the number into 4 regions :
1st: Trailing zeros .
2nd: The lowest digit not in Region 1.
3rd: Consecutive 9s starting with the digit above Region 2.
4th: All remaining digits.

Then the next number is :
[Region 4+1] [Region 1] [Region 2-1] [Region 3] .

Example:
Input Number = 548995000
Region 1 : 000
Region 2 : 5
Region 3 : 99
Region 4 : 548

Next number = 549000499

Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// CPP program to find next greater number with
// same sum of digits.
#include <bits/stdc++.h>
using namespace std;
  
#define pb push_back
  
void getnext(int arr[], int n)
{
    // for storing 4 regions
    vector<int> a1, a2, a3, a4;
  
    // trailing zeros region1
    int i = n - 1; // last index
    while (arr[i] == 0) 
    {
        a1.pb(0);
        i--;
    }
  
    // lowest region(region 2) not in region 1
    a2.pb(arr[i--]); 
  
    // Consecutive 9's   (region 3)
    while (arr[i] == 9) 
    {
        a3.pb(9);
        i--;
    }
  
    int j = 0;
    while (arr[j] == 0)
        j++; // Starting zeros
  
    while (j <= i) // 4th region
    {
        a4.pb(arr[j]);
        j++;
    }
  
    // Calculation of result
    j = a4.size() - 1;
  
    a4[j]++; // Region4 + 1
  
    a2[0]--; // Region2 -1
  
    int l = a1.size() + a2.size() + a3.size() + a4.size();
  
    // Calculating the result
    j = n-1;
    i = a3.size() - 1;
  
    // Copying the third region
    while (i >= 0)
    {
        arr[j--] = a3[i--];
    }
  
    // Copying the 2nd region
    i = a2.size() - 1;
    while (i >= 0) 
    {
        arr[j--] = a2[i--];
    }
  
    // Copying the 1st region
    i = a1.size() - 1;
    while (i >= 0) 
    {
        arr[j--] = a1[i--];
    }
  
    // Copying the 4th region
    i = a4.size() - 1;
    while (i >= 0) 
    {
        arr[j--] = a4[i--];
    }
  
    while (j >= 0)
        arr[j--] = 0;
}
  
int main()
{
    int arr[] = { 0, 0, 0, 0, 0, 0, 0, 3, 9, 7, 
                0, 0, 2, 9, 8, 9, 5, 9, 9, 0 };
    int n = sizeof(arr)/sizeof(arr[0]);
  
    getnext(arr, n); // Calling the function
  
    for (int i = 0; i < n; i++)
        cout << arr[i];
  
    return 0;
}

chevron_right


Output:

00000003970029896089


My Personal Notes arrow_drop_up