Java 检查数字是否为泛数字的最快算法?
泛数字是包含数字1..number长度的数字。Java 检查数字是否为泛数字的最快算法?,java,c#,algorithm,Java,C#,Algorithm,泛数字是包含数字1..number长度的数字。 例如123、4312和967412385 我已经解决了许多欧拉项目的问题,但超数字问题总是超过一分钟规则 这是我的泛数字功能: private boolean isPandigital(int n){ Set<Character> set= new TreeSet<Character>(); String string = n+""; for (char c:string.toCharArray
例如123、4312和967412385 我已经解决了许多欧拉项目的问题,但超数字问题总是超过一分钟规则 这是我的泛数字功能:
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();
}
private boolean isPandigital(int n){
Set=新树集();
字符串字符串=n+“”;
for(char c:string.toCharArray()){
如果(c='0')返回false;
增加(c);
}
返回set.size()==string.length();
}
创建自己的函数并使用此方法进行测试
int pans=0;
for (int i=123456789;i<=123987654;i++){
if (isPandigital(i)){
pans++;
}
}
intpans=0;
对于(inti=123456789;i您可以改进的两件事:
- 不需要使用集合:可以使用包含10个元素的布尔数组
- 使用除法和模运算(%)来提取数字,而不是转换为字符串
您可以添加:
if (set.add(c)==false) return false;
这将大大缩短您的计算时间,因为一旦找到重复项,它将返回false,因为在这种情况下返回false。这是我的解决方案:
static char[][] pandigits = new char[][]{
"1".toCharArray(),
"12".toCharArray(),
"123".toCharArray(),
"1234".toCharArray(),
"12345".toCharArray(),
"123456".toCharArray(),
"1234567".toCharArray(),
"12345678".toCharArray(),
"123456789".toCharArray(),
};
private static boolean isPandigital(int i)
{
char[] c = String.valueOf(i).toCharArray();
Arrays.sort(c);
return Arrays.equals(c, pandigits[c.length-1]);
}
在我的(相当慢的)系统上以0.3秒的时间运行循环。C#,17ms,如果你真的想检查的话
类程序
{
静态bool IsPandigital(int n)
{
整数位数=0;整数计数=0;整数tmp;
对于(;n>0;n/=10,++计数)
{
如果((tmp=数字)=(数字|=1=变换[decreasingpart+1]),首先;
--递减部分);
//整个序列按降序排列,已完成
如果(减少部分<0)屈服断裂;
//在递减分区中找到最小的元素,即
//大于(或等于)递减分区前面的项
int大于等于长度-1;
对于(;较大>递减部分&)
变换[decreasingpart]。第一个>=变换[greater]。第一个;
大——);
//将两者互换
交换(参考变换[递减部分]、参考变换[更大];
//反转递减分区
数组。反转(变换,递减部分+1,长度-递减部分-1);
收益回报申请转换(项目、转换);
}
}
#区域重载
公共静态IEnumerable置换(T[]项)
{
返回排列(项目,空);
}
公共静态IEnumerable置换(IEnumerable项、IComparer比较器)
{
列表=新列表(项目);
返回排列(list.ToArray(),比较器);
}
公共静态IEnumerable置换(IEnumerable项)
{
返回排列(项目,空);
}
#端域重载
#区域效用
公共静态IEnumerable应用程序转换(
T[]项,
IntPair[]转换)
{
for(int i=0;i
我的解决方案涉及总和和乘积。
这是C#格式的,在我的笔记本电脑上运行大约180毫秒:
static int[] sums = new int[] {1, 3, 6, 10, 15, 21, 28, 36, 45};
static int[] products = new int[] {1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
static void Main(string[] args)
{
var pans = 0;
for (var i = 123456789; i <= 123987654; i++)
{
var num = i.ToString();
if (Sum(num) == sums[num.Length - 1] && Product(num) == products[num.Length - 1])
pans++;
}
Console.WriteLine(pans);
}
protected static int Sum(string num)
{
int sum = 0;
foreach (char c in num)
sum += (int) (c - '0');
return sum;
}
protected static int Product(string num)
{
int prod = 1;
foreach (char c in num)
prod *= (int)(c - '0');
return prod;
}
static int[]sums=新的int[]{1,3,6,10,15,21,28,36,45};
静态int[]产品=新int[]{1,2,6,24,120,720,5040,40320,362880};
静态void Main(字符串[]参数)
{
var-pans=0;
对于(var i=123456789;i
为什么要在你能做的时候找到呢
J很好地做到了这一点:
isPandigital =: 3 : 0
*./ (' ' -.~ ": 1 + i. # s) e. s =. ": y
)
isPandigital"0 (123456789 + i. 1 + 123987654 - 123456789)
isPandigital=:3:0
*./(''-.~“:1+i.#s)e.s=.“:y
)
isPandigital“0(123456789+i.1+123987654-123456789)
但是慢慢地。我会修改。现在,计时4.8秒
编辑:
如果它正好位于两个集合编号123456789和123987654之间,则此表达式:
*./"1 (1+i.9) e."1 (9#10) #: (123456789 + i. 1 + 123987654 - 123456789)
*./“1(1+i.9)e.”1(9#10)#:(123456789+i.1+123987654-123456789)
运行时间为0.23秒。与J中的速度一样快,是蛮力风格。bool IsPandigital(无符号长n){
bool IsPandigital (unsigned long n) {
if (n <= 987654321) {
hash_map<int, int> m;
unsigned long count = (unsigned long)(log((double)n)/log(10.0))+1;
while (n) {
++m[n%10];
n /= 10;
}
while (m[count]==1 && --count);
return !count;
}
return false;
}
bool IsPandigital2 (unsigned long d) {
// Avoid integer overflow below if this function is passed a very long number
if (d <= 987654321) {
unsigned long sum = 0;
unsigned long prod = 1;
unsigned long n = d;
unsigned long max = (log((double)n)/log(10.0))+1;
unsigned long max_sum = max*(max+1)/2;
unsigned long max_prod = 1;
while (n) {
sum += n % 10;
prod *= (n%10);
max_prod *= max;
--max;
n /= 10;
}
return (sum == max_sum) && (prod == max_prod);
}
如果(n机器管理员是正确的。至少对于一些问题,最好迭代所有的泛数字,检查每个泛数字是否符合问题的标准。但是,我认为他们的代码不太正确
在这种情况下,我不确定哪一个更好:发布新答案还是编辑他们的答案。无论如何,我认为这是修改后的Python代码,尽管它不会生成0到n的泛数字
from itertools import *
def generate_pandigital(length):
'Generate all 1-to-length pandigitals'
return (''.join(each) for each in list(permutations('123456789'[:length])))
def test():
for i in range(10):
print 'Generating all %d-digit pandigitals' % i
for (n,p) in enumerate(generate_pandigital(i)):
print n,p
if __name__=='__main__':
test()
在123456789到123987654的范围内,这个c#实现比@andras快8%左右,但在我的测试盒上很难看到他的运行时间是14毫秒,而这个运行时间是13毫秒
static bool IsPandigital(int n)
{
int count = 0;
int digits = 0;
int digit;
int bit;
do
{
digit = n % 10;
if (digit == 0)
{
return false;
}
bit = 1 << digit;
if (digits == (digits |= bit))
{
return false;
}
count++;
n /= 10;
} while (n > 0);
return (1<<count)-1 == digits>>1;
}
static bool IsPandigital(int n)
{
整数计数=0;
整数位数=0;
整数位数;
整数位;
做
{
数字=n%10;
如果(数字==0)
{
返回false;
}
位=1 0);
返回(11;
}
如果我们平均100次运行的结果,我们可以得到一个小数点
public void Test()
{
int pans = 0;
var sw = new Stopwatch();
sw.Start();
for (int count = 0; count < 100; count++)
{
pans = 0;
for (int i = 123456789; i <= 123987654; i++)
{
if (IsPandigital(i))
{
pans++;
}
}
}
sw.Stop();
Console.WriteLine("{0}pcs, {1}ms", pans, sw.ElapsedMilliseconds / 100m);
}
公共无效测试()
{
int pans=0;
var sw=新秒表();
sw.Start();
用于(int count=0;count<100;count++)
{
pans=0;
对于(int i=123456789;i 1;
}
编辑:将n/=10集成到数字计算中,以实现小的速度改进
bool IsPandigital (unsigned long n) {
if (n <= 987654321) {
hash_map<int, int> m;
unsigned long count = (unsigned long)(log((double)n)/log(10.0))+1;
while (n) {
++m[n%10];
n /= 10;
}
while (m[count]==1 && --count);
return !count;
}
return false;
}
bool IsPandigital2 (unsigned long d) {
// Avoid integer overflow below if this function is passed a very long number
if (d <= 987654321) {
unsigned long sum = 0;
unsigned long prod = 1;
unsigned long n = d;
unsigned long max = (log((double)n)/log(10.0))+1;
unsigned long max_sum = max*(max+1)/2;
unsigned long max_prod = 1;
while (n) {
sum += n % 10;
prod *= (n%10);
max_prod *= max;
--max;
n /= 10;
}
return (sum == max_sum) && (prod == max_prod);
}
from itertools import *
def generate_pandigital(length):
'Generate all 1-to-length pandigitals'
return (''.join(each) for each in list(permutations('123456789'[:length])))
def test():
for i in range(10):
print 'Generating all %d-digit pandigitals' % i
for (n,p) in enumerate(generate_pandigital(i)):
print n,p
if __name__=='__main__':
test()
static bool IsPandigital(int n)
{
int count = 0;
int digits = 0;
int digit;
int bit;
do
{
digit = n % 10;
if (digit == 0)
{
return false;
}
bit = 1 << digit;
if (digits == (digits |= bit))
{
return false;
}
count++;
n /= 10;
} while (n > 0);
return (1<<count)-1 == digits>>1;
}
public void Test()
{
int pans = 0;
var sw = new Stopwatch();
sw.Start();
for (int count = 0; count < 100; count++)
{
pans = 0;
for (int i = 123456789; i <= 123987654; i++)
{
if (IsPandigital(i))
{
pans++;
}
}
}
sw.Stop();
Console.WriteLine("{0}pcs, {1}ms", pans, sw.ElapsedMilliseconds / 100m);
}
private static bool IsPandigital(int n)
{
int count = 0;
int digits = 0;
int digit;
int bit;
do
{
digit = n - ((n / 10) * 10);
if (digit == 0)
{
return false;
}
bit = 1 << digit;
if (digits == (digits |= bit))
{
return false;
}
count++;
n /= 10;
} while (n > 0);
return (1 << count) - 1 == digits >> 1;
}
private static bool IsPandigital(int n)
{
int count = 0;
int digits = 0;
int digit;
int bit;
do
{
digit = n - ((n /= 10) * 10);
if (digit == 0)
{
return false;
}
bit = 1 << digit;
if (digits == (digits |= bit))
{
return false;
}
count++;
} while (n > 0);
return (1 << count) - 1 == digits >> 1;
}
public class GenPandigits
{
/**
* The prefix that must be appended to every number, like 123.
*/
int prefix;
/**
* Length in characters of the prefix.
*/
int plen;
/**
* The digit from which to start the permutations
*/
String beg;
/**
* The length of the required Pandigital numbers.
*/
int len;
/**
* @param prefix If there is no prefix then this must be null
* @param beg If there is no prefix then this must be "1"
* @param len Length of the required numbers (excluding the prefix)
*/
public GenPandigits(String prefix, String beg, int len)
{
if (prefix == null)
{
this.prefix = 0;
this.plen = 0;
}
else
{
this.prefix = Integer.parseInt(prefix);
this.plen = prefix.length();
}
this.beg = beg;
this.len = len;
}
public StringBuffer genPermsBet()
{
StringBuffer b = new StringBuffer(beg);
for(int k=2;k<=len;k++)
{
StringBuffer rs = new StringBuffer();
int l = b.length();
int s = l/(k-1);
String is = String.valueOf(k+plen);
for(int j=0;j<k;j++)
{
rs.append(b);
for(int i=0;i<s;i++)
{
rs.insert((l+s)*j+i*k+j, is);
}
}
b = rs;
}
return b;
}
public int[] getPandigits(String buffer)
{
int[] pd = new int[buffer.length()/len];
int c= prefix;
for(int i=0;i<len;i++)
c =c *10;
for(int i=0;i<pd.length;i++)
pd[i] = Integer.parseInt(buffer.substring(i*len, (i+1)*len))+c;
return pd;
}
public static void main(String[] args)
{
GenPandigits gp = new GenPandigits("123", "4", 6);
//GenPandigits gp = new GenPandigits(null, "1", 6);
long beg = System.currentTimeMillis();
StringBuffer pansstr = gp.genPermsBet();
long end = System.currentTimeMillis();
System.out.println("Time = " + (end - beg));
int pd[] = gp.getPandigits(pansstr.toString());
long end1 = System.currentTimeMillis();
System.out.println("Time = " + (end1 - end));
}
}
GenPandigits gp = new GenPandigits(null, "1", 9);
bool IsPandigital(int n)
{
if (n != 9 * (int)((0x1c71c71dL * n) >> 32))
return false;
int flags = 0;
while (n > 0) {
int q = (int)((0x1999999aL * n) >> 32);
flags |= 1 << (n - q * 10);
n = q;
}
return flags == 0x3fe;
}
#include <cstdio>
#include <ctime>
bool isPandigital(long num)
{
int arr [] = {1,2,3,4,5,6,7,8,9}, G, count = 9;
do
{
G = num%10;
if (arr[G-1])
--count;
arr[G-1] = 0;
} while (num/=10);
return (!count);
}
int main()
{
clock_t start(clock());
int pans=0;
for (int i = 123456789;i <= 123987654; ++i)
{
if (isPandigital(i))
++pans;
}
double end((double)(clock() - start));
printf("\n\tFound %d Pandigital numbers in %lf seconds\n\n", pans, end/CLOCKS_PER_SEC);
return 0;
}
public static List<String> permutation(String str) {
List<String> permutations = new LinkedList<String>();
permutation("", str, permutations);
return permutations;
}
private static void permutation(String prefix, String str, List<String> permutations) {
int n = str.length();
if (n == 0) {
permutations.add(prefix);
} else {
for (int i = 0; i < n; i++) {
permutation(prefix + str.charAt(i),
str.substring(0, i) + str.substring(i + 1, n), permutations);
}
}
}
public static boolean is1To9PanDigit(int i) {
if (i < 1e8) {
return false;
}
BitSet set = new BitSet();
while (i > 0) {
int mod = i % 10;
if (mod == 0 || set.get(mod)) {
return false;
}
set.set(mod);
i /= 10;
}
return true;
}
public static boolean is1ToNPanDigit(int i, int n) {
BitSet set = new BitSet();
while (i > 0) {
int mod = i % 10;
if (mod == 0 || mod > n || set.get(mod)) {
return false;
}
set.set(mod);
i /= 10;
}
return set.cardinality() == n;
}
public static boolean is0To9PanDigit(long i) {
if (i < 1e6) {
return false;
}
BitSet set = new BitSet();
if (i <= 123456789) { // count for leading zero
set.set(0);
}
while (i > 0) {
int mod = (int) (i % 10);
if (set.get(mod)) {
return false;
}
set.set(mod);
i /= 10;
}
return true;
}
public static int maxPanDigit(int n) {
StringBuffer sb = new StringBuffer();
for(int i = n; i > 0; i--) {
sb.append(i);
}
return Integer.parseInt(sb.toString());
}
public static int minPanDigit(int n) {
StringBuffer sb = new StringBuffer();
for(int i = 1; i <= n; i++) {
sb.append(i);
}
return Integer.parseInt(sb.toString());
}
def is_pandigital(n, zero_full=True, base=10):
"""Returns True or False if the number n is pandigital.
This function returns True for formal pandigital numbers as well as
n-pandigital
"""
r, l = 0, 0
while n:
l, r, n = l + 1, r + n % base, n / base
t = xrange(zero_full ^ 1, l + (zero_full ^ 1))
return r == sum(t) and l == len(t)
boolean isPandigital(int num,int length){
for(int i=1;i<=length;i++){
if(!(num+"").contains(i+""))
return false;
}
return true;
}
static boolean isPandigital(int num){
for(int i=1;i<=(num+"").length();i++){
if(!(num+"").contains(i+""))
return false;
}
return true;
}
extension Int {
func isPandigital() -> Bool {
let requiredBitmask = 0b1111111111;
let minimumPandigitalNumber = 1023456789;
if self >= minimumPandigitalNumber {
var resultBitmask = 0b0;
var digits = self;
while digits != 0 {
let lastDigit = digits % 10;
let binaryCodedDigit = 1 << lastDigit;
resultBitmask |= binaryCodedDigit;
// remove last digit
digits /= 10;
}
return resultBitmask == requiredBitmask;
}
return false;
}
}
1023456789.isPandigital(); // true
bool IsPandigital(long long number, int n){
int arr[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, amax = 0, amin;
while (number > 0){
int rem = number % 10;
arr[rem]--;
if (arr[rem] < 0)
return false;
number = number / 10;
}
for (int i = 0; i < n; i++){
if (i == 0)
amin = arr[i];
if (arr[i] > amax)
amax = arr[i];
if (arr[i] < amin)
amin = arr[i];
}
if (amax == 0 && amin == 0)
return true;
else
return false;