Это по линии Кибби, но я был немного заинтригован этим, прежде чем он написал и решил:
long mask ( long n ) {
long m = n % 10;
long n_d = n;
long div = 10;
int shl = 0;
while ( n_d >= 10 ) {
n_d /= 10;
long t = n_d % 10;
m |= ( t << ( shl += 4 ));
}
return m;
}
boolean findMatch( int a, int b ) {
if ( b < a ) return false;
if ( a == b ) return true;
long m_a = mask( a ); // set up mask O(n)
long m_b = mask( b ); // set up mask O(m)
while ( m_a < m_b ) {
if (( m_a & m_b ) == m_a ) return true;
m_a <<= 4; // shift - fast!
if ( m_a == m_b ) return true;
} // O(p)
return false;
}
void testContains( int a, int b ) {
print( "findMatch( " + a + ", " + b + " )=" + findMatch( a, b ));
}
testContains( 12, 120 );
testContains( 12, 125 );
testContains( 123, 551241238 );
testContains( 131, 1214124 );
testContains( 131, 1314124 );
Поскольку 300 символов - это слишком мало, чтобы приводить аргументы, я редактирую этот основной пост, чтобы ответить на "Пиролистику".
В отличие от OP, я не был удивлен, что нативный скомпилированный indexOf был быстрее, чем код Java с примитивами. Поэтому моя цель не состояла в том, чтобы найти что-то, что, как мне показалось, было быстрее, чем нативный метод, называемый миллионы раз по всему Java-коду.
ОП ясно дал понять, что это была не производственная проблема, а скорее по линии праздного любопытства, поэтому мой ответ разрешает это любопытство. Я предположил, что скорость была проблемой, когда он пытался решить ее в процессе производства, но из любопытства «этот метод будет вызываться миллионы и миллионы раз» больше не применяется. Как он должен был объяснить одному постеру, его больше не используют в качестве производственного кода, поэтому сложность больше не имеет значения.
Кроме того, он обеспечивает единственную реализацию на странице, которой удается найти «123» в «551241238», поэтому, если правильность не является посторонней проблемой, он обеспечивает это. Также пространство решения «алгоритма, который решает проблему математически с использованием примитивов Java, но опережает оптимизированный нативный код», может быть EMPTY .
Плюс, из вашего комментария не ясно, сравнивали ли вы яблоки с яблоками. Функциональной спецификацией является f (int, int) -> boolean, а не f (String, String) -> boolean (что является разновидностью домена indexOf
). Так что, если вы не протестируете что-то подобное (что все еще может побить мою, и я не буду сильно удивлен), дополнительные накладные расходы могут съесть некоторые из этих 40%.
boolean findMatch( int a, int b ) {
String s_a = "" + a;
String s_b = "" + b;
return s_a.indexOf( s_b ) > -1;
}
Выполняет те же основные шаги. log 10 (a) кодировка + log 10 (b) кодировка + фактическое нахождение соответствия, что также O ( n ) где n - самый большой логарифм.