如何找出所有回文数字

时间:2011-06-19 08:14:14

标签: java algorithm

palindromic number或数字回文是一个“对称”数字,如16461,当数字反转时保持不变。

术语回文来自回文,它指的是转子这样的词,在其字母的反转下保持不变。

第一个回文数字(十进制)是:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22,
33, 44, 55, 66, 77, 88, 99, 101, 111,
121, 131, 141, 151, 161, 171, 181,
191, ...

如何查找下面的所有回文数字,比如10000?

8 个答案:

答案 0 :(得分:27)

恢复你的推理。不要试图找到这些数字,而是创建它们。 您可以简单地取任何数字并对其进行镜像(总是长度均匀)并且对于相同的数字,只需在它们之间添加0..9(对于具有奇数长度的数字)。

答案 1 :(得分:15)

生成所有回文到特定限制。

public static Set<Integer> allPalindromic(int limit) {

    Set<Integer> result = new HashSet<Integer>();

    for (int i = 0; i <= 9 && i <= limit; i++)
        result.add(i);

    boolean cont = true;
    for (int i = 1; cont; i++) {
        StringBuffer rev = new StringBuffer("" + i).reverse();
        cont = false;
        for (String d : ",0,1,2,3,4,5,6,7,8,9".split(",")) {
            int n = Integer.parseInt("" + i + d + rev);
            if (n <= limit) {
                cont = true;
                result.add(n);
            }
        }
    }

    return result;
}


测试回文性

使用字符串

public static boolean isPalindromic(String s, int i, int j) {
    return j - i < 1 || s.charAt(i) == s.charAt(j) && isPalindromic(s,i+1,j-1);
}

public static boolean isPalindromic(int i) {
    String s = "" + i;
    return isPalindromic(s, 0, s.length() - 1);
}

使用整数

public static boolean isPalindromic(int i) {
    int len = (int) Math.ceil(Math.log10(i+1));
    for (int n = 0; n < len / 2; n++)
        if ((i / (int) Math.pow(10, n)) % 10 !=
            (i / (int) Math.pow(10, len - n - 1)) % 10)
            return false;
    return true;
}

答案 2 :(得分:3)

有一种蛮力方法,你循环遍历所有数字并检查它们是否是回文。要检查,请反转数字并进行比较。复杂性应为O(n log10(n))。 [不是log10()很重要,但为了完整起见。 ]

另一种是根据数字生成回文。假设您必须生成5位数的回文,它们的形式为ABCBA,所以只需循环0-9并填充所有位置。现在,如果您产生低于10 ^ 4的回文,则产生1,2,3和4位数的回文。

我写了快速(和肮脏)的C ++代码来测试两种算法的速度(8位数的回文)。 蛮力:Ideone.(3.4s) 更好的算法:Ideone.(0s)

我删除了print语句,因为Ideone不允许在输出中使用这个大数据。

在我的电脑上,时间是:

Brute force:
real    0m7.150s
user    0m7.052s
Better algorithm:
real    0m0.024s
user    0m0.012s

我知道您已经将语言称为Java,但我不了解Java,这些代码只是向您展示算法之间的差异,您可以编写自己的Java代码。

PS:我已经用蛮力测试了我的代码8位数的回文,不能确定它是否对8位以上产生错误,尽管使用的方法是一般的。此外,我本来希望在评论中提供代码链接,因为已经提到了正确的方法,但我没有所需的权限。

答案 3 :(得分:2)

一种方法是简单地迭代所有数字,并检查每个数字:它是否是回文,如下:

public static boolean isPalindrome(Integer x) {
        String s = x.toString();
        int len = s.length();
        for (int i = 0;i<len;i+=2) {
            if (s.charAt(i) != s.charAt(len-i-1)) return false;
        }
        return true;
    }
public static void main(String[] args) {
        int N = 10000;
        for (Integer x = 0;x<N;x++) { 
            if (isPalindrome(x)) System.out.println(x);
        }
    } 

答案 4 :(得分:1)

蛮力方法:从1 ... 10000创建一个foreach循环并测试约束。更简单的是,将数字转换为字符串,将其反转并将其与原始值进行比较。这是低效率和蹩脚的。

更好的方法:考虑回文模式。考虑到回文的不同可能性,取决于数字的长度。现在提供一种生成给定长度的回文的方法。 (我不会这样做,因为这显然是家庭作业。)

答案 5 :(得分:1)

类似于下面的循环可用于打印回文数:

for(int i = 1; i <= 9; i++) {
        for(int j = 0; j <= 9; j++) {
            for(int k = 0; k <= 9; k++) {
                System.out.println("" + i + j + k + j + i);
            }
        }
    }

答案 6 :(得分:0)

我在C#中编写这些方法可能会有所帮助。 main方法构建了一个包含给定位数的所有回文数的确定列表。它的快速和评论贯穿其中,以帮助解释我使用过程。

我还提供了一些支持方法,包括快速回文测试,值得指出的是pow10 [x]是10的幂数组,以进一步提高速度。

    public static List<ulong> GetPalindromicNumbers(ulong digits = 3) 
    {
        List<ulong> result = new List<ulong>(1000);
        ulong limit = pow10[digits] - 1;

        // Add the palindromes 1 to 9
        for ( ulong b = 1; b < 10; b++ )    
            result.Add( b );    

        ulong pow = 10; // Used to limit the creation of odd and even palindromes between powers of 10
        ulong a = 1;    // Working value which is used to set the next set of digits for abc
        ulong palindrome = 9;
        while ( palindrome < limit )
        {
            // Build even digit palindromes of the form abc + cba where abc is any number and cba is the same number with its digits reversed
            while ( a < pow  )
            {
                // If 'abc' has trailing 0s they will be lost if we try to reverse it. We need to overcome this sop we check for trailing 0's 
                // and add them to abc. eg if abc starts at 100, abc becomes 10000 and cba becomes 1 which when joined correctly forms 100001
                ulong abc = a;
                ulong cba = a;
                while ( cba % 10 == 0 )
                {
                    abc *= 10;
                    cba /= 10;
                }
                palindrome = MathExt.Concat( abc , MathExt.ReverseDigits( cba ) );        
                result.Add( palindrome );       // Add palindromes of the form abc + cba
                a++;
            }

            // Build odd digit palindromes of the form lhs + b + rhs where lhs is any number and rhs is the same number with its digits reversed
            a /= 10;
            if ( palindrome == limit ) break;   // Check to see if we have the required palindromic numbers
            while ( a < pow  )
            {
                // Handle the special case of when b = 0 
                // Increase leftside by a factor of 10 for each trailing zero as these 0s will be lost when the leftside is reversed
                // This approach does away with the need to convert numbers with trailing zeros to strings before they are reversed.
                ulong lhs = a;
                ulong rhs = a;
                while ( rhs % 10 == 0 )
                {
                    lhs *= 10;
                    rhs /= 10;
                }
                palindrome = MathExt.Concat( lhs * 10, MathExt.ReverseDigits( rhs ) );      // Multiplying the lhs by 10 is equivalent to adding b == 0
                result.Add( palindrome );       // Add numbers of the form aaa + 0 + aaa

                lhs = a;
                for ( ulong b = 1; b != 10; b++ )
                {
                    rhs = a * 10 + b; // Adding b before we reverse guarantees that there is no trailing 0s
                    palindrome = MathExt.Concat( lhs, MathExt.ReverseDigits( rhs ) );       // Works except when b == 0
                    result.Add( palindrome );       // Add numbers of the form aaa + b + aaa
                }
                a++;
            }
            pow *= 10;        // Each pass of the outer loop add an extra digit to aaa
        } 
        return (result);
    }


    /// <summary>
    ///  Reverses the digits in a number returning it as a new number. Trailing '0's will be lost.
    /// </summary>
    /// <param name="n">The number to reverse.</param>
    /// <param name="radix">The radix or base of the number to reverse.</param>
    /// <returns>The reversed number.</returns>
    static public ulong ReverseDigits( ulong n, uint radix = 10 )
    {
        // Reverse the number
        ulong result = 0;
        do
        {
            // Extract the least significant digit using standard modular arithmetric
            result *= radix;
            result += n % radix;
            n /= radix;
        } while ( n != 0 );
        return (result);
    }


/// <summary>
    /// Concaternates the specified numbers 'a' and 'b' forming a new number 'ab'.
    /// </summary>
    /// <example>If a = 1234 and b = 5678 then Concat(a,b) = 12345678.</example>
    /// <param name="a">The first number.</param>
    /// <param name="b">The second number.</param>
    /// <returns>The concaternated number 'ab'.</returns>
    public static ulong Concat( this ulong a, ulong b )
    {
        // Concaternate the two numbers by shifting 'a' to the left by the number of digits in 'b' and then adding 'b'
        return (a * pow10[NumberOfDigits( b )] + b);
    }

    /// <summary>
    /// Evaluate whether the passed integer is a palindrome in base 10 or not.
    /// </summary>
    /// <param name="n">Integer to test.</param>
    /// <returns>True - Palindrome, False - Non palindrome.</returns>
    static public bool IsPalindrome( this ulong n )
    {
        uint divisor = NumberOfDigits( n ) - 1;
        do
        {
            // Extract the most and least significant digits of (n)
            ulong msd = n / pow10[divisor];
            ulong lsd = n % 10;

            // Check they match!
            if ( msd != lsd )
                return (false);

            // Remove the msd and lsd from (n) and test the next most and least significant digits.
            n -= msd * pow10[divisor];  // Remove msd
            n /= 10;                    // Remove lsd
            divisor -= 2;               // Number has reduced in size by 2 digits 
        } while ( n != 0 );
        return (true);
    }

答案 7 :(得分:0)

import Queue
import copy

def printPalindromesTillK(K):
    q = Queue.Queue(K);
    for i in range(0, 10):
        q.put(str(i));
        q.put(str(i) + str(i));
    while(not q.empty()):
        elem = q.get();
        print  elem;
        for i in range(1, 10):
            item = str(i) + elem + str(i);
            if int(item) <= K:
               q.put(item); 

print printPalindromesTillK(10000);