数字可以是1到10 15 。 我正在使用此代码,但它已经没时间了。
int distinct(long long int a)
{
int ele[10]={0},i,c=0;
if(a==0) return 1;
if(a<0) a=a*-1;
while(a)
{
int t=a%10;
ele[t]=1;
a=a/10;
}
for (i=0;i<10;i++)
if (ele[i])
c++;
return c;
}
答案 0 :(得分:1)
结合各种想法并解决UB。
IMO,怀疑OP遗漏了一些导致缓慢的重要原因。// 1 to 10^15 only
int distinct_fast(long long int a) {
int ele[10]={0},i,c=0;
do {
ele[a%10]=1;
a /= 10;
} while(a);
i=10-1;
do {
c += ele[i]; // @barak manos
}
} while (i-- > 0);
return c;
}
// entire unsigned long long range method 1
int distinct_complete1(unsigned long long int a) {
... // same code as above
// entire long long range method 2
int distinct_complete2(long long int a) {
int ele[10]={0},i,c=0;
// Use (-) numbers as there are more (or the same) number of (+) numbers
if (a > 0) a = -a;
do {
ele[-(a % 10)] = 1;
a /= 10;
} while(a);
// same as above
...
OP探索的想法:
unsigned char ele[10]={0}; // smaller flags
。
do {
if (ele[a%10]++ == 0) c++;
a /= 10;
} while(a);
// This eliminates need for following loop to add `ele[]`
// Invoke some strategy so when when a is small enough,
// use `long` ops rather than `long long`
if (a > 1000000000) {
for (i=6; i-- > 0; ) {
if (ele[a%10]++ == 0) c++;
a /= 10;
}
}
unsigned long b = a;
do {
if (ele[b%10]++ == 0) c++;
b /= 10;
} while(b);
int distinct_complete3(unsigned long long int a) {
unsigned char ele[10]={0};
int c = 0;
do {
if (ele[a%10]++ == 0) c++;
a /= 10;
} while(a);
return c;
}
答案 1 :(得分:0)
几种可能的优化:
你可以用模数换取乘法,通常要快得多:q= a / 10; m= a - 10 * q;
你可以通过将所有标志打包在一个整数中来避免最后的计数循环,让mask
;用mask= 0
初始化它;每当您找到一个数字(m
)时,请用mask|= (1 << m)
标记;最后,计数将由bits[mask]
给出,其中bits
是一个向量,包含从0
到1023=2^10-1
的所有整数的预先计算的计数。
int distinct(long long int a)
{
int mask= 0;
while (a)
{
int q= a / 10, m= a - 10 * q;
mask|= 1 << m;
a= q;
}
static short bits[1024]= { 0, 1, 1, 2, 1, 2, 2, 3, ...}; // Number of bits set
return bits[mask];
}
更好的是,您可以使用组中的数字,例如三个。而不是转换为基数10,转换为基数1000.并且对于每个基数1000&#34;数字&#34;,计算标记组成十进制数字的相应掩码(例如,535
产生掩码{{ 1}})。
这应该快三倍。无论如何,应该添加对前导零的一些关注,例如为前导三元组提供一个独特的掩码阵列(1<<5 | 1<<3 | 1<<5 = 40
vs ..1
)。
001
使用静态数组确保它们一次性加载。