📌  相关文章
📜  给定一个数字,找到下一个最小的回文

📅  最后修改于: 2021-04-24 16:16:44             🧑  作者: Mango

给定一个数字,找到比该数字大的下一个最小回文。例如,如果输入数字为“ 2 3 5 4 5”,则输出应为“ 2 3 6 3 2”。如果输入数字为“ 9 9 9”,则输出应为“ 1 0 0 1”。
假定输入为数组。数组中的每个条目代表输入数字中的一个数字。令数组为“ num []”,数组大小为“ n”

可能有三种不同类型的输入需要分别处理。
1)输入的数字是回文,并且全为9。例如“ 9 9 9”。输出应为“ 1 0 0 1”
2)输入的号码不是回文。例如“ 1 2 3 4”。输出应为“ 1 3 3 1”
3)输入的数字是回文,并且不全为9。例如“ 1 2 2 1”。输出应为“ 1 3 3 1”。

输入类型1的解决方案很简单。输出包含n +1个数字,其中转角数字为1,而转角数字之间的所有数字均为0。
现在让我们首先讨论输入类型2和3。如何将给定数字转换为更大的回文?为了理解该解决方案,让我们首先定义以下两个术语:

左侧:给定数字的左半部分。 “ 1 2 3 4 5 6”的左侧是“ 1 2 3”,“ 1 2 3 4 5”的左侧是“ 1 2”

右侧:给定数字的右半部分。 “ 1 2 3 4 5 6”的右侧是“ 4 5 6”,“ 1 2 3 4 5”的右侧是“ 4 5”

要转换为回文,我们可以取其左侧的镜子,也可以取其右侧的镜子。但是,如果我们拿右边的镜子,那么形成的回文就不能保证是下一个更大的回文。因此,我们必须拿起左侧的镜子并将其复制到右侧。但是有些情况下必须以不同的方式处理。请参阅以下步骤。
我们将从两个索引i和j开始。我指向两个中间元素(或者在n为奇数的情况下指向中间元素周围的两个元素)。我们一步一步地将i和j彼此分开。

步骤1.首先,忽略与右侧对应部分相同的左侧部分。例如,如果数字为“ 8 3 4 2 2 4 6 9 9”,我们将忽略中间的四个元素。我现在指向元素3,j现在指向元素6。

步骤2.在步骤1之后,出现以下情况:
情况1:指标i和j越过边界。
当输入数字是回文式时,会发生这种情况。在这种情况下,我们只需将1加到中间数字(或n等于偶数的数字)向左侧的MSB数字传播进位,并同时将左侧的镜像复制到右侧。
例如,如果给定的数字是“ 1 2 9 2 1”,我们将9递增到10并传播进位。因此数字变为“ 1 3 0 3 1”

情况2:左侧和右侧之间留有不相同的数字。因此,我们只是将左侧镜像到右侧,并尝试最小化形成的数量以保证下一个最小的回文。
在这种情况下,可以有两个子情况

2.1)复制左侧到右侧就足够了,我们不需要增加任何数字,结果只是左侧的镜像。以下是此子案例的一些示例。
下一个回文“ 7 8 3 3 2 2”是“ 7 8 3 3 8 7”
下一个回文“ 1 2 5 3 2 2”是“ 1 2 5 5 2 1”
“ 1 4 5 8 7 6 7 8 3 2 2”的下一个回文是“ 1 4 5 8 7 6 7 8 5 4 1”
我们如何检查这种情况?我们需要检查的只是步骤1中被忽略部分之后的数字。该数字在上面的示例中突出显示。如果该数字大于右侧数字中的相应数字,则将左侧复制到右侧就足够了,我们无需执行其他任何操作。

2.2)仅将左侧复制到右侧是不够的。当左侧的上述定义的数字较小时,会发生这种情况。以下是这种情况的一些示例。
“ 7 1 3 3 2 2”的下一个回文是“ 7 1 4 4 1 7”
“ 1 2 3 4 6 2 8”的下一个回文是“ 1 2 3 5 3 2 1”
“ 9 4 1 8 7 9 7 8 3 2 2”的下一个回文是“ 9 4 1 8 8 0 8 8 1 4 9”
我们像情况1一样处理这种子情况。我们只向中间数字(或n表示偶数的数字)加1,将进位向左侧的MSB数字传播,同时将左侧的镜像复制到右侧。

C++
#include 
using namespace std;
 
// Utility that prints out an array on a line
void printArray(int arr[], int n)
{
    int i;
    for(i = 0; i < n; i++)
        printf("%d ", arr[i]);
         
    printf("\n");
}
 
// A utility function to check if num has all 9s
int AreAll9s(int* num, int n )
{
    int i;
    for(i = 0; i < n; ++i)
        if (num[i] != 9)
            return 0;
             
    return 1;
}
 
// Returns next palindrome of a given number num[].
// This function is for input type 2 and 3
void generateNextPalindromeUtil (int num[], int n )
{
     
    // Find the index of mid digit
    int mid = n / 2;
 
    // A bool variable to check if copy of left
    // side to right is sufficient or not
    bool leftsmaller = false;
 
    // End of left side is always 'mid -1'
    int i = mid - 1;
 
    // Beginning of right side depends
    // if n is odd or even
    int j = (n % 2) ? mid + 1 : mid;
 
   // Initially, ignore the middle same digits
    while (i >= 0 && num[i] == num[j])
        i--, j++;
 
    // Find if the middle digit(s) need to be
    // incremented or not (or copying left
    // side is not sufficient)
    if (i < 0 || num[i] < num[j])
        leftsmaller = true;
 
    // Copy the mirror of left to tight
    while (i >= 0)
    {
        num[j] = num[i];
        j++;
        i--;
    }
 
    // Handle the case where middle digit(s) must
    // be incremented. This part of code is for
    // CASE 1 and CASE 2.2
    if (leftsmaller == true)
    {
        int carry = 1;
        i = mid - 1;
 
        // If there are odd digits, then increment
        // the middle digit and store the carry
        if (n % 2 == 1)
        {
            num[mid] += carry;
            carry = num[mid] / 10;
            num[mid] %= 10;
            j = mid + 1;
        }
        else
            j = mid;
 
        // Add 1 to the rightmost digit of the
        // left side, propagate the carry towards
        // MSB digit and simultaneously copying
        // mirror of the left side to the right side.
        while (i >= 0)
        {
            num[i] += carry;
            carry = num[i] / 10;
            num[i] %= 10;
             
            // Copy mirror to right
            num[j++] = num[i--];
        }
    }
}
 
// The function that prints next palindrome
// of a given number num[] with n digits.
void generateNextPalindrome(int num[], int n)
{
    int i;
 
    printf("Next palindrome is:");
 
    // Input type 1: All the digits are 9, simply o/p 1
    // followed by n-1 0's followed by 1.
    if (AreAll9s(num, n))
    {
        printf("1 ");
        for(i = 1; i < n; i++)
            printf("0 ");
             
        printf("1");
    }
 
    // Input type 2 and 3
    else
    {
        generateNextPalindromeUtil(num, n);
 
        // print the result
        printArray (num, n);
    }
}
 
// Driver code
int main()
{
    int num[] = { 9, 4, 1, 8, 7, 9, 7, 8, 3, 2, 2 };
 
    int n = sizeof(num) / sizeof(num[0]);
 
    generateNextPalindrome(num, n);
 
    return 0;
}
 
// This code is contributed by rohan07


C
#include 
 
// A utility function to print an array
void printArray (int arr[], int n);
 
// A utility function to check if num has all 9s
int AreAll9s (int num[], int n );
 
// Returns next palindrome of a given number num[].
// This function is for input type 2 and 3
void generateNextPalindromeUtil (int num[], int n )
{
    // find the index of mid digit
    int mid = n/2;
 
    // A bool variable to check if copy of left side to right is sufficient or not
    bool leftsmaller = false;
 
    // end of left side is always 'mid -1'
    int i = mid - 1;
 
    // Beginning of right side depends if n is odd or even
    int j = (n % 2)? mid + 1 : mid;
 
   // Initially, ignore the middle same digits
    while (i >= 0 && num[i] == num[j])
        i--,j++;
 
    // Find if the middle digit(s) need to be incremented or not (or copying left
    // side is not sufficient)
    if ( i < 0 || num[i] < num[j])
        leftsmaller = true;
 
    // Copy the mirror of left to tight
    while (i >= 0)
    {
        num[j] = num[i];
        j++;
        i--;
    }
 
    // Handle the case where middle digit(s) must be incremented.
    // This part of code is for CASE 1 and CASE 2.2
    if (leftsmaller == true)
    {
        int carry = 1;
        i = mid - 1;
 
        // If there are odd digits, then increment
        // the middle digit and store the carry
        if (n%2 == 1)
        {
            num[mid] += carry;
            carry = num[mid] / 10;
            num[mid] %= 10;
            j = mid + 1;
        }
        else
            j = mid;
 
        // Add 1 to the rightmost digit of the left side, propagate the carry
        // towards MSB digit and simultaneously copying mirror of the left side
        // to the right side.
        while (i >= 0)
        {
            num[i] += carry;
            carry = num[i] / 10;
            num[i] %= 10;
            num[j++] = num[i--]; // copy mirror to right
        }
    }
}
 
// The function that prints next palindrome of a given number num[]
// with n digits.
void generateNextPalindrome( int num[], int n )
{
    int i;
 
    printf("Next palindrome is:");
 
    // Input type 1: All the digits are 9, simply o/p 1
    // followed by n-1 0's followed by 1.
    if( AreAll9s( num, n ) )
    {
        printf( "1 ");
        for( i = 1; i < n; i++ )
            printf( "0 " );
        printf( "1" );
    }
 
    // Input type 2 and 3
    else
    {
        generateNextPalindromeUtil ( num, n );
 
        // print the result
        printArray (num, n);
    }
}
 
// A utility function to check if num has all 9s
int AreAll9s( int* num, int n )
{
    int i;
    for( i = 0; i < n; ++i )
        if( num[i] != 9 )
            return 0;
    return 1;
}
 
/* Utility that prints out an array on a line */
void printArray(int arr[], int n)
{
    int i;
    for (i=0; i < n; i++)
        printf("%d ", arr[i]);
    printf("\n");
}
 
// Driver Program to test above function
int main()
{
    int num[] = {9, 4, 1, 8, 7, 9, 7, 8, 3, 2, 2};
 
    int n = sizeof (num)/ sizeof(num[0]);
 
    generateNextPalindrome( num, n );
 
    return 0;
}


Java
// Java program to find next smallest
// palindrome
 
public class nextplaindrome
{
    // Returns next palindrome of a given
    // number num[]. This function is for
    // input type 2 and 3
    static void generateNextPalindromeUtil(int num[], int n)
    {
        int mid = n / 2;
 
        // end of left side is always 'mid -1'
        int i = mid - 1;
         
        // Beginning of right side depends
        // if n is odd or even
        int j = (n % 2 == 0) ? mid : mid + 1;
         
        // A bool variable to check if copy of left
        // side to right
        // is sufficient or not
        boolean leftsmaller = false;
 
        // Initially, ignore the middle same digits
        while (i >= 0 && num[i] == num[j])
        {
            i--;
            j++;
        }
         
        // Find if the middle digit(s) need to
        // be incremented or not (or copying left
        // side is not sufficient)
        if (i < 0 || num[i] < num[j])
        {
            leftsmaller = true;
        }
         
        // Copy the mirror of left to tight
        while (i >= 0)
        {
            num[j++] = num[i--];
        }
         
        // Handle the case where middle digit(s)
        // must be incremented. This part of code
        // is for CASE 1 and CASE 2.2
        if (leftsmaller)
        {
            int carry = 1;
         
            // If there are odd digits, then increment
            // the middle digit and store the carry
            if (n % 2 == 1) {
                num[mid] += 1;
                carry = num[mid] / 10;
                num[mid] %= 10;
            }
            i = mid - 1;
            j = (n % 2 == 0 ? mid : mid + 1);
             
            // Add 1 to the rightmost digit of the left
            // side, propagate the carry towards MSB digit
            // and simultaneously copying mirror of the
            // left side to the right side.
            //when carry is zero no need to loop through till i>=0
            while (i >= 0 && carry>0) 
            {
                num[i] = num[i] + carry;
                carry = num[i] / 10;
                num[i] %= 10;
                num[j] = num[i];// copy mirror to right
                i--;
                j++;
            }
 
        }
    }
 
    // The function that prints next palindrome
    // of a given number num[] with n digits.
    static void generateNextPalindrome(int num[], int n)
    {
        System.out.println("Next Palindrome is:");
         
        // Input type 1: All the digits are 9,
        // simply o/p 1 followed by n-1 0's
        // followed by 1.
        if (isAll9(num, n)) {
            System.out.print("1");
            for (int i = 0; i < n - 1; i++)
                System.out.print("0");
            System.out.println("1");
 
        }
     
        // Input type 2 and 3
        else {
            generateNextPalindromeUtil(num, n);
            printarray(num);
        }
    }
 
    // A utility function to check if num has all 9s
    static boolean isAll9(int num[], int n) {
        for (int i = 0; i < n; i++)
            if (num[i] != 9)
                return false;
        return true;
    }
 
    /* Utility that prints out an array on a line */
    static void printarray(int num[]) {
        for (int i = 0; i < num.length; i++)
            System.out.print(num[i]);
        System.out.println();
    }
 
    public static void main(String[] args)
    {
        int num[] = { 9, 4, 1, 8, 7, 9, 7, 8, 3, 2, 2 };
        generateNextPalindrome(num, num.length);
    }
}


Python3
# Returns next palindrome of a given number num[].
# This function is for input type 2 and 3
def generateNextPalindromeUtil (num, n) :
 
    # find the index of mid digit
    mid = int(n/2 )
 
    # A bool variable to check if copy of left
    # side to right is sufficient or not
    leftsmaller = False
 
    # end of left side is always 'mid -1'
    i = mid - 1
 
    # Beginning of right side depends
    # if n is odd or even
    j = mid + 1 if (n % 2) else mid
 
    # Initially, ignore the middle same digits
    while (i >= 0 and num[i] == num[j]) :
        i-=1
        j+=1
 
    # Find if the middle digit(s) need to be
    # incremented or not (or copying left
    # side is not sufficient)
    if ( i < 0 or num[i] < num[j]):
        leftsmaller = True
 
    # Copy the mirror of left to tight
    while (i >= 0) :
     
        num[j] = num[i]
        j+=1
        i-=1
     
 
    # Handle the case where middle
    # digit(s) must be incremented.
    # This part of code is for CASE 1 and CASE 2.2
    if (leftsmaller == True) :
     
        carry = 1
        i = mid - 1
 
        # If there are odd digits, then increment
        # the middle digit and store the carry
        if (n%2 == 1) :
         
            num[mid] += carry
            carry = int(num[mid] / 10 )
            num[mid] %= 10
            j = mid + 1
         
        else:
            j = mid
 
        # Add 1 to the rightmost digit of the
        # left side, propagate the carry
        # towards MSB digit and simultaneously
        # copying mirror of the left side
        # to the right side.
        while (i >= 0) :
         
            num[i] += carry
            carry = int(num[i] / 10)
            num[i] %= 10
            num[j] = num[i] # copy mirror to right
            j+=1
            i-=1
         
# The function that prints next
# palindrome of a given number num[]
# with n digits.
def generateNextPalindrome(num, n ) :
 
    print("\nNext palindrome is:")
 
    # Input type 1: All the digits are 9, simply o/p 1
    # followed by n-1 0's followed by 1.
    if( AreAll9s( num, n ) == True) :
     
        print( "1")
        for i in range(1, n):
            print( "0" )
        print( "1")
     
 
    # Input type 2 and 3
    else:
     
        generateNextPalindromeUtil ( num, n )
 
        # print the result
        printArray (num, n)
     
# A utility function to check if num has all 9s
def AreAll9s(num, n ):
    for i in range(1, n):
        if( num[i] != 9 ) :
            return 0
    return 1
 
 
# Utility that prints out an array on a line
def printArray(arr, n):
 
    for i in range(0, n):
        print(int(arr[i]),end=" ")
    print()
 
 
# Driver Program to test above function
if __name__ == "__main__":
    num = [9, 4, 1, 8, 7, 9, 7, 8, 3, 2, 2]
    n = len(num)
    generateNextPalindrome( num, n )
 
# This code is contributed by Smitha Dinesh Semwal


C#
// C# program to find next smallest  palindrome
using System;
public class GFG {
     
    // Returns next palindrome of a given
    // number num[]. This function is for
    // input type 2 and 3
    static void generateNextPalindromeUtil(int []num, int n)
    {
        int mid = n / 2;
 
        // end of left side is always 'mid -1'
        int i = mid - 1;
         
        // Beginning of right side depends
        // if n is odd or even
        int j = (n % 2 == 0) ? mid : mid + 1;
         
        // A bool variable to check if copy of left
        // side to right
        // is sufficient or not
        bool leftsmaller = false;
 
        // Initially, ignore the middle same digits
        while (i >= 0 && num[i] == num[j])
        {
            i--;
            j++;
        }
         
        // Find if the middle digit(s) need to
        // be incremented or not (or copying left
        // side is not sufficient)
        if (i < 0 || num[i] < num[j])
        {
            leftsmaller = true;
        }
         
        // Copy the mirror of left to tight
        while (i >= 0)
        {
            num[j++] = num[i--];
        }
         
        // Handle the case where middle digit(s)
        // must be incremented. This part of code
        // is for CASE 1 and CASE 2.2
        if (leftsmaller)
        {
            int carry = 1;
         
            // If there are odd digits, then increment
            // the middle digit and store the carry
            if (n % 2 == 1) {
                num[mid] += 1;
                carry = num[mid] / 10;
                num[mid] %= 10;
            }
            i = mid - 1;
            j = (n % 2 == 0 ? mid : mid + 1);
             
            // Add 1 to the rightmost digit of the left
            // side, propagate the carry towards MSB digit
            // and simultaneously copying mirror of the
            // left side to the right side.
            while (i >= 0)
            {
                num[i] = num[i] + carry;
                carry = num[i] / 10;
                num[i] %= 10;
                num[j] = num[i];// copy mirror to right
                i--;
                j++;
            }
 
        }
    }
 
    // The function that prints next palindrome
    // of a given number num[] with n digits.
    static void generateNextPalindrome(int []num, int n)
    {
        Console.WriteLine("Next Palindrome is:");
         
        // Input type 1: All the digits are 9,
        // simply o/p 1 followed by n-1 0's
        // followed by 1.
        if (isAll9(num, n)) {
            Console.Write("1");
            for (int i = 0; i < n - 1; i++)
                Console.Write("0");
            Console.Write("1");
 
        }
     
        // Input type 2 and 3
        else {
            generateNextPalindromeUtil(num, n);
            printarray(num);
        }
    }
 
    // A utility function to check if num has all 9s
    static bool isAll9(int[] num, int n) {
        for (int i = 0; i < n; i++)
            if (num[i] != 9)
                return false;
        return true;
    }
 
    /* Utility that prints out an array on a line */
    static void printarray(int []num) {
        for (int i = 0; i < num.Length; i++)
            Console.Write(num[i]+ " ");
        Console.Write(" ");
    }
 
    // Driver code
    public static void Main()
    {
        int []num = { 9, 4, 1, 8, 7, 9, 7, 8, 3, 2, 2 };
        generateNextPalindrome(num, num.Length);
    }
}
 
// This code is contributed by Smitha.


PHP
= 0 &&
           $num[$i] == $num[$j])
    {
        $i--;
        $j++;
    }
     
    // Find if the middle digit(s)
    // need to be incremented or
    // not (or copying left side
    // is not sufficient)
    if ($i < 0 || $num[$i] < $num[$j])
    {
        $leftsmaller = true;
    }
     
    // Copy the mirror
    // of left to tight
    while ($i >= 0)
    {
        $num[$j++] = $num[$i--];
    }
     
    // Handle the case where
    // middle digit(s) must be
    // incremented. This part
    // of code is for CASE 1
    // and CASE 2.2
    if ($leftsmaller)
    {
        $carry = 1;
     
        // If there are odd digits,
        // then increment the middle
        // digit and store the carry
        if ($n % 2 == 1)
        {
            $num[$mid] += 1;
            $carry = (int)($num[$mid] / 10);
            $num[$mid] %= 10;
        }
        $i = $mid - 1;
        $j = ($n % 2 == 0 ?
                     $mid : $mid + 1);
         
        // Add 1 to the rightmost digit
        // of the left side, propagate
        // the carry towards MSB digit
        // and simultaneously copying
        // mirror of the left side to
        // the right side.
        while ($i >= 0)
        {
            $num[$i] = $num[$i] + $carry;
            $carry = (int)($num[$i] / 10);
            $num[$i] %= 10;
             
            // copy mirror to right
            $num[$j] = $num[$i];
            $i--;
            $j++;
        }
 
    }
return $num;
}
 
// The function that prints
// next palindrome of a given
// number num[] with n digits.
function generateNextPalindrome($num, $n)
{
    echo "Next Palindrome is:\n";
     
    // Input type 1: All the
    // digits are 9, simply
    // o/p 1 followed by n-1
    // 0's followed by 1.
    if (isAll9($num, $n))
    {
        echo "1";
        for ($i = 0; $i < $n - 1; $i++)
            echo "0";
        echo "1";
 
    }
 
    // Input type 2 and 3
    else
    {
        $num = generateNextPalindromeUtil($num, $n);
            printarray($num);
    }
}
 
// A utility function to
// check if num has all 9s
function isAll9($num, $n)
{
    for ($i = 0; $i < $n; $i++)
        if ($num[$i] != 9)
            return false;
    return true;
}
 
/* Utility that prints out
an array on a line */
function printarray($num)
{
    for ($i = 0;
         $i < count($num); $i++)
        echo $num[$i];
    echo "\n";
}
 
// Driver code
$num = array(9, 4, 1, 8, 7,
             9, 7, 8, 3, 2, 2);
generateNextPalindrome($num,
               count($num));
 
// This code is contributed by mits.
?>


Javascript


输出:

Next palindrome is:
9 4 1 8 8 0 8 8 1 4 9