Хорошо, узнав, что такое обратный поиск, я думаю, вы можете сделать это:
const char kLetters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int get_index(char letter)
{
return letter - 'A';
}
В конце концов, буква A
находится в индексе 0
, B
в 1
, C
в 2
... и так далее. Это дает достаточно подсказки.
My O (1) раствор
.
Пока что другие решения работают для непроизвольной последовательности букв, а решение @awoodland предполагает, что буква, индекс которой должен быть получен, известна во время компиляции , что делает ее менее полезен
Но это решение попыталось решить оба ограничения; то есть должно работать:
С произвольной последовательностью букв, такой как
const char Letters[] = "ZBADCEWFVGHIUXJTKSLYQMROPN";
И буквы могут быть неизвестно во время компиляции. Функция, которая получает индекс, имеет следующую подпись:
int Index(char letter);
Вот полный код, который использует технику, описанную @ David Rodríguez в его блоге :
#include <iostream>
const char Letters[] = "ZBADCEWFVGHIUXJTKSLYQMROPN";
template<char L> int Index();
template<> int Index<'Z'>() { return 0; }
template<> int Index<'B'>() { return 1; }
template<> int Index<'A'>() { return 2; }
template<> int Index<'D'>() { return 3; }
template<> int Index<'C'>() { return 4; }
template<> int Index<'E'>() { return 5; }
template<> int Index<'W'>() { return 6; }
template<> int Index<'F'>() { return 7; }
template<> int Index<'V'>() { return 8; }
template<> int Index<'G'>() { return 9; }
template<> int Index<'H'>() { return 10; }
template<> int Index<'I'>() { return 11; }
template<> int Index<'U'>() { return 12; }
template<> int Index<'X'>() { return 13; }
template<> int Index<'J'>() { return 14; }
template<> int Index<'T'>() { return 15; }
template<> int Index<'K'>() { return 16; }
template<> int Index<'S'>() { return 17; }
template<> int Index<'L'>() { return 18; }
template<> int Index<'Y'>() { return 19; }
template<> int Index<'Q'>() { return 20; }
template<> int Index<'M'>() { return 21; }
template<> int Index<'R'>() { return 22; }
template<> int Index<'O'>() { return 23; }
template<> int Index<'P'>() { return 24; }
template<> int Index<'N'>() { return 25; }
typedef int (*fptr)();
const int limit = 26;
fptr indexLookup[ limit ];
template <char L>
struct init_indexLookup {
static void init( fptr *indexLookup ) {
indexLookup[ L - 'A' ] = &Index<L>;
init_indexLookup<L-1>::init( indexLookup );
}
};
template <>
struct init_indexLookup<'A'> {
static void init( fptr *indexLookup ) {
indexLookup[ 0 ] = &Index<'A'>;
}
};
const int ignore = (init_indexLookup<'Z'>::init(indexLookup),0);
int Index(char letter)
{
return indexLookup[letter-'A']();
}
А вот и код теста:
int main()
{
std::cout << Index('A') << std::endl;
std::cout << Index('Z') << std::endl;
std::cout << Index('B') << std::endl;
std::cout << Index('K') << std::endl;
}
Выход:
2
0
1
16
Онлайн демо: http://ideone.com/uzE2t
Ну, на самом деле это два вызова функций: один на Index()
, другой на один в indexLookup
. Вы можете легко избежать первого вызова функции, написав ( ideone ):
int main()
{
std::cout << indexLookup['A'-'A']() << std::endl;
std::cout << indexLookup['Z'-'A']() << std::endl;
std::cout << indexLookup['B'-'A']() << std::endl;
std::cout << indexLookup['K'-'A']() << std::endl;
}
Это выглядит громоздко, но эй, мы можем сделать Index()
inline:
inline int Index(char letter)
{
return indexLookup[letter-'A']();
}
Это выглядит нормально, и, скорее всего, теперь компилятор сделает это эквивалентным одному вызову функции!
Простое, но O (1) решение
Подождите. Я только что понял, что все решение сводится к таблице поиска, которая инициализируется как:
const int indexLookup[] = {2,1,4,3,5,7,9,10,11,14,16,18,21,
25,23,24,20,22,17,15,12,8,6,13,19,0};
inline int Index(char letter)
{
return indexLookup[letter-'A'];
}
, что выглядит невероятно просто!