当前位置: 首页 > 面试题库 >

检查数字是否为泛数字的最快算法?

李耀
2023-03-14
问题内容

Pandigital数字是包含数字1..number长度的数字。
例如123、4312和967412385。

我已经解决了许多Euler项目问题​​,但是Pandigital问题总是超过一分钟法则。

这是我的泛指功能:

private boolean isPandigital(int n){
    Set<Character> set= new TreeSet<Character>();   
    String string = n+"";
    for (char c:string.toCharArray()){
        if (c=='0') return false;
        set.add(c);
    }
    return set.size()==string.length();
}

创建自己的函数并使用此方法对其进行测试

int pans=0;
for (int i=123456789;i<=123987654;i++){
    if (isPandigital(i)){
         pans++;
    }
}

使用此循环,您应该获得720个pandigital号码。我的平均时间是500毫秒。

我正在使用Java,但问题是所有语言都可以使用。

UPDATE
@andras答案到目前为止是最好的时间,但是@Sani Huttunen答案启发了我添加一个新算法,该算法几乎与@andras同时获得。


问题答案:

C#,17毫秒,如果您真的要 检查

class Program
{
    static bool IsPandigital(int n)
    {
        int digits = 0; int count = 0; int tmp;

        for (; n > 0; n /= 10, ++count)
        {
            if ((tmp = digits) == (digits |= 1 << (n - ((n / 10) * 10) - 1)))
                return false;
        }

        return digits == (1 << count) - 1;
    }

    static void Main()
    {
        int pans = 0;
        Stopwatch sw = new Stopwatch();
        sw.Start();
        for (int i = 123456789; i <= 123987654; i++)
        {
            if (IsPandigital(i))
            {
                pans++;
            }
        }
        sw.Stop();
        Console.WriteLine("{0}pcs, {1}ms", pans, sw.ElapsedMilliseconds);
        Console.ReadKey();
    }
}

对于与基数10中的Wikipedia定义一致的检查:

const int min = 1023456789;
const int expected = 1023;

static bool IsPandigital(int n)
{
    if (n >= min)
    {
        int digits = 0;

        for (; n > 0; n /= 10)
        {
            digits |= 1 << (n - ((n / 10) * 10));
        }

        return digits == expected;
    }
    return false;
}

要枚举给定范围内的数字,生成排列就足够了。

从严格意义上讲,以下内容并不是您的问题的答案,因为它没有实施检查。它使用未针对此特殊情况进行优化的通用置换实现-
仍会在13ms内生成所需的720置换(换行符可能会弄乱):

static partial class Permutation
{
    /// <summary>
    /// Generates permutations.
    /// </summary>
    /// <typeparam name="T">Type of items to permute.</typeparam>
    /// <param name="items">Array of items. Will not be modified.</param>
    /// <param name="comparer">Optional comparer to use.
    /// If a <paramref name="comparer"/> is supplied, 
    /// permutations will be ordered according to the 
    /// <paramref name="comparer"/>
    /// </param>
    /// <returns>Permutations of input items.</returns>
    public static IEnumerable<IEnumerable<T>> Permute<T>(T[] items, IComparer<T> comparer)
    {
        int length = items.Length;
        IntPair[] transform = new IntPair[length];
        if (comparer == null)
        {
            //No comparer. Start with an identity transform.
            for (int i = 0; i < length; i++)
            {
                transform[i] = new IntPair(i, i);
            };
        }
        else
        {
            //Figure out where we are in the sequence of all permutations
            int[] initialorder = new int[length];
            for (int i = 0; i < length; i++)
            {
                initialorder[i] = i;
            }
            Array.Sort(initialorder, delegate(int x, int y)
            {
                return comparer.Compare(items[x], items[y]);
            });
            for (int i = 0; i < length; i++)
            {
                transform[i] = new IntPair(initialorder[i], i);
            }
            //Handle duplicates
            for (int i = 1; i < length; i++)
            {
                if (comparer.Compare(
                    items[transform[i - 1].Second], 
                    items[transform[i].Second]) == 0)
                {
                    transform[i].First = transform[i - 1].First;
                }
            }
        }

        yield return ApplyTransform(items, transform);

        while (true)
        {
            //Ref: E. W. Dijkstra, A Discipline of Programming, Prentice-Hall, 1997
            //Find the largest partition from the back that is in decreasing (non-icreasing) order
            int decreasingpart = length - 2;
            for (;decreasingpart >= 0 && 
                transform[decreasingpart].First >= transform[decreasingpart + 1].First;
                --decreasingpart) ;
            //The whole sequence is in decreasing order, finished
            if (decreasingpart < 0) yield break;
            //Find the smallest element in the decreasing partition that is 
            //greater than (or equal to) the item in front of the decreasing partition
            int greater = length - 1;
            for (;greater > decreasingpart && 
                transform[decreasingpart].First >= transform[greater].First; 
                greater--) ;
            //Swap the two
            Swap(ref transform[decreasingpart], ref transform[greater]);
            //Reverse the decreasing partition
            Array.Reverse(transform, decreasingpart + 1, length - decreasingpart - 1);
            yield return ApplyTransform(items, transform);
        }
    }

    #region Overloads

    public static IEnumerable<IEnumerable<T>> Permute<T>(T[] items)
    {
        return Permute(items, null);
    }

    public static IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> items, IComparer<T> comparer)
    {
        List<T> list = new List<T>(items);
        return Permute(list.ToArray(), comparer);
    }

    public static IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> items)
    {
        return Permute(items, null);
    }

    #endregion Overloads

    #region Utility

    public static IEnumerable<T> ApplyTransform<T>(
        T[] items, 
        IntPair[] transform)
    {
        for (int i = 0; i < transform.Length; i++)
        {
            yield return items[transform[i].Second];
        }
    }

    public static void Swap<T>(ref T x, ref T y)
    {
        T tmp = x;
        x = y;
        y = tmp;
    }

    public struct IntPair
    {
        public IntPair(int first, int second)
        {
            this.First = first;
            this.Second = second;
        }
        public int First;
        public int Second;
    }

    #endregion
}

class Program
{

    static void Main()
    {
        int pans = 0;
        int[] digits = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        Stopwatch sw = new Stopwatch();
        sw.Start();
        foreach (var p in Permutation.Permute(digits))
        {
            pans++;
            if (pans == 720) break;
        }
        sw.Stop();
        Console.WriteLine("{0}pcs, {1}ms", pans, sw.ElapsedMilliseconds);
        Console.ReadKey();
    }
}


 类似资料:
  • 问题内容: 我有一个,并且想知道最快的方法是检查所有值是否均为零? 有没有比做更快的方法: 问题答案: 我先将所有字节加总后就重写了这个答案,但是这是不正确的,因为Java已经对字节进行了签名,因此我需要or。 另外,我已将JVM预热更改为正确。 最好的选择实际上是简单地遍历所有值。 我想您有三种主要选择: 或所有元素并检查总和。 进行无分支比较。 与分支进行比较。 我不知道使用Java添加字节的

  • 问题内容: 如何检查数字是否为小数? 使用Objective-C: 问题答案: 如果将数字四舍五入(可以使用下限功能来完成),然后从原始数字中减去该数字,则会得到两者之间的差。 编辑- 我的原始答案建议计算数字与其下限等值之间的差,以查看小数点后是否有任何单位。但是,如后面所述,可能存在舍入错误,这会导致内存中值的表示与实际含义略有不同。 例如,3.0可以表示为3.00000000000001,因

  • 问题内容: 是否有任何方法或快速方法来检查Java中数字是否为整数(属于Z字段)? 我考虑过从四舍五入的数字中减去它,但是我没有找到任何可以帮助我解决这个问题的方法。 我应该在哪里检查?整数Api? 问题答案: 又快又脏… 编辑:假设x已经是其他数字形式。如果要处理字符串,请查看。

  • 问题内容: 检查字符串是否仅包含字母数字字符的最快方法是什么。 我有一些代码会占用大量CPU,我想知道是否有比使用预编译正则表达式更快的方法。 问题答案: 我已经编写了使用正则表达式(根据其他答案)与不使用正则表达式进行比较的测试。在运行Java 1.6的四核OSX10.8计算机上进行的测试 有趣的是,使用正则表达式比手动迭代字符串要慢5到10倍。此外,该功能比的速度略快。一种支持允许扩展Unic

  • 问题内容: 检查字符串是否可以在Python中表示为数字的最佳方法是什么? 我目前拥有的功能是: 它不仅丑陋且缓慢,而且看起来笨拙。但是我还没有找到更好的方法,因为调用floatmain函数甚至更糟。 问题答案: 如果您要解析(正数,无符号)整数而不是浮点数,则可以将该isdigit()函数用于字符串对象。 字符串方法- isdigit():Python2,Python3

  • 本文向大家介绍检查数字是否为斐波那契数字或JavaScript,包括了检查数字是否为斐波那契数字或JavaScript的使用技巧和注意事项,需要的朋友参考一下 我们需要编写一个JavaScript函数,该函数接受一个数字并根据斐波那契数列是否包含该事实返回一个布尔值。 例如- 如果函数调用是这样的- 那么输出应该是- 现在,让我们为这个问题写一个递归解决方案- 示例 输出结果 控制台中的输出将为-