以下是我编写的2种算法,以确定2个数字是否具有相同的数字和长度。例如:
如果有任何不明确的地方,请发表评论,我会添加更多细节。
问题是:有没有更好的方法来进行此项检查?在任何方面都更好:效率(时间和/或空间),代码可读性,角落案件处理等。例如,第一种方法存在整数溢出的风险,但只要数字不大,可能是一种正常的方法,因为时间 - 复杂性是线性的。 感谢您的反馈。
哈希与素数:
如果两个散列的值相同,则表示数字具有相同的数字和长度
public static boolean haveSameDigitsAndLengthPrimes(int a, int b) {
int[] primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
int hashA=1, hashB=1;
while (a > 0) {
hashA *= primes[a%10];
a /= 10;
}
while (b > 0) {
hashB *= primes[b%10];
b /= 10;
}
return (hashA == hashB);
}
计数数字方法:
如果辅助数组中的任何值不等于0,则表示2个数字不满足所需条件
public static boolean haveSameDigitsAndLength(int a, int b) {
int[] digits = new int[10];
for (int i=a; i>0; i=i/10) {
++digits[i%10];
}
for (int i=b; i>0; i=i/10) {
--digits[i%10];
}
for (int digit : digits) {
if (digit != 0) {
return false;
}
}
return true;
}
2.b中。计数数字方法:实施改进:
public static boolean haveSameDigitsAndLength(int a, int b) {
if ((a == 0 || b == 0) && a != b) {
return false;
}
int[] digits = new int[10];
int i=a, j=b;
for (; i>0 && j>0; i/=10, j/=10) {
++digits[i%10];
--digits[j%10];
}
if (i != 0 || j != 0) {
return false;
}
for (int digit : digits) {
if (digit != 0) {
return false;
}
}
return true;
}
测试案例:
答案 0 :(得分:1)
我说的是第二种方法。您可以通过合并前两个循环来删除一个循环。
bool TestEqual(int a, int b) {
int cnts[10] = {0}, i = a, j = b;
for (; i && j; i /= 10, j /= 10) {
cnts[i % 10]++;
cnts[j % 10]--;
}
return !i && !j;
for (i = 0; i < 10; ++i) {
if (cnts[i] != 0) break;
}
return i == 10;
}
我的C ++代码,但你理解逻辑。您的方法至少有两个好处。
int
s的最小长度。counts
位数。答案 1 :(得分:1)
我可以建议其他一些次要优化,以改善空间,时间...可读性很简单。假设基数为10(十进制)!
1)首先检查数字计数。具有相同数字长度的两个随机数的机会很小。如果您有快速的DigitCheck方法,则不会浪费时间。 2)取消使用数组。我使用两个变量作为位字段。我使用简单的移位方法对每个数字中每个数字[0,..,9]的频率进行编码。 3)由于仅使用2个位域,因此我只需要进行一次比较即可确认所有频率相同或不相同!在伪代码中:
ulong encode += 1 << (LeastSignificantDigit(number) * 6) // number % 10
我选择了6乘法器,因为6位可以安全地保存ulong中任何数字的最大频率。
public static bool IsDigitAnagram( this ulong a, ulong b )
{
// CHECK equality of digit counts.
if( Digits( a ) == Digits( b ) )
{
// CALCULATE the frequency of digits in each number.
ulong encodeA = 0;
ulong encodeB = 0;
while( a != 0 )
{
encodeA += 1UL << ( ( int )LeastSignificantDigit( a ) * 6 ); // a % 10;
a = ShiftRight( a ); // a /= 10;
encodeB += 1UL << ( ( int )LeastSignificantDigit( b ) * 6 );
b = ShiftRight( b );
}
// CONFIRM if the digit frequencies are identical in which case they are anagrams of each other.
return ( encodeA == encodeB );
}
return ( false );
}
答案 2 :(得分:0)
在Python中,您可以:
bucket-owner-full-control
答案 3 :(得分:0)
我使用 Javascript 做了同样的事情。如果是线性时间,请检查并让我反馈您是否可以改进?
function sameFrequency(num1, num2) {
let digits1 = num1.toString().split('');
let digits2 = num2.toString().split('');
if (digits1.length !== digits2.length) {
return false;
}
let obj1 = {};
let obj2 = {};
for (const n of digits1) {
obj1[n] = (obj1[n] || 0 ) + 1;
}
for (const n of digits2) {
obj2[n] = (obj2[n] || 0 ) + 1;
}
for (const val in obj1) {
if (!(val in obj2)) {
return false
}
if (obj1[val] !== obj2[val]) {
return false;
}
}
return true
};
console.log(sameFrequency(181, 811));
console.log(sameFrequency(34, 14));
console.log(sameFrequency(182, 281));
console.log(sameFrequency(3589578, 5879385));
console.log(sameFrequency(22, 222));