Показаны сообщения с ярлыком Java. Показать все сообщения
Показаны сообщения с ярлыком Java. Показать все сообщения

воскресенье, 9 февраля 2014 г.

Интересная оптимизация линейного поиска

Посмотрим сегодня на всеми известный классический алгоритм линейного поиска:

  1. public static int linearSearch(int[] a, int x) {
  2.  
  3. int length = a.length;
  4.  
  5. for (int i = 0; i < length; ++i) {
  6. if (a[i] == x) {
  7. return i;
  8. }
  9. }
  10.  
  11. return -1;
  12. }

Вроде все с ним хорошо, но данный алгоритм можно сделать еще эффективнее. Если внимательно присмотреться, то на каждом витке цикла мы делаем две проверки: не закончился ли наш массив и непосредственно само сравнение с искомым элементом.

Давайте исправим алгоритм так, что на каждом витке цикла мы будем осуществлять только одну проверку. Для этого воспользуемся одним приемом: настроим входные данные так, чтобы искомый элемент всегда находился. Запомним последний элемент в массиве и поставим на его место искомый элемент.

Далее запускаем цикл и проверяем только на совпадение с образцом. Цикл в любом случае закончится. В конце вернем последний элемент на место и сделаем простую проверку. Если мы не дошли до конца или последний элемент равен искомому, то наш поиск увенчался успехом.

  1. public static int sentinelLinearSearch(int[] a, int x) {
  2.  
  3. int lastIndex = a.length - 1;
  4. int last = a[lastIndex];
  5.  
  6. a[lastIndex] = x;
  7.  
  8. int i = 0;
  9. while (a[i] != x) {
  10. ++i;
  11. }
  12.  
  13. a[lastIndex] = last;
  14.  
  15. if (i < lastIndex || a[lastIndex] == x) {
  16. return i;
  17. }
  18.  
  19. return -1;
  20. }