Как написать метод LessThan без использования оператора

Как бы вы рекурсивно написали метод, который проверяет, меньше ли число, чем другое, без использования оператора '‹'?

  1. Вы можете использовать только операторы «плюс», «минус», «умножить» и «равно».
  2. Он должен быть рекурсивным
  3. x и y всегда будут 0 или больше
  4. Должен вернуть boolean
  5. При необходимости вы можете использовать другие методы, но они должны соответствовать приведенным выше правилам.

Ков у меня есть до сих пор:

public static boolean isLessThan(int x, int y) { 
    if(x == y - 1) return true;
    if(x == y + 1) return false; 
    if(x == y) return false; 

    return isLessThan((x), (y-1)) || isLessThan((x-1), y);
}

person Sarim A.    schedule 22.10.2017    source источник
comment
Разрешен ли побитовый оператор?   -  person Erfan Ahmed    schedule 22.10.2017
comment
public static boolean isLessThan (int x, int y) { if (x == y - 1) return true; если (х == у + 1) вернуть ложь; если (х == у) вернуть ложь; вернуть isLessThan((x), (y-1)) || меньше чем ((х-1), у); }   -  person Sarim A.    schedule 22.10.2017
comment
@ErfanAhmedEmon Извините, побитовое И и Или разрешено   -  person Sarim A.    schedule 22.10.2017
comment
вы использовали оператор «минус» в своем коде, но вы сказали «используйте только операторы «плюс», «умножение» и «равно». Означает ли это, что минус также разрешен?   -  person Erfan Ahmed    schedule 22.10.2017
comment
@ErfanAhmedEmon минус разрешен, извините за путаницу   -  person Sarim A.    schedule 22.10.2017
comment
Вы близко. Два вопроса: 1) Что происходит с LessThan(3,1)? 2) Что мотивирует вас иметь две ветви рекурсии?   -  person MFisherKDX    schedule 22.10.2017
comment
@MFisherKDX 1. Мы получаем переполнение стека 2. Я пытаюсь рассмотреть 2 случая, когда у нас может быть (1, 3) или (3, 1), и не знаю, как различить их в коде.   -  person Sarim A.    schedule 22.10.2017


Ответы (2)


Поскольку вы сделали добросовестную попытку, написав свой собственный код, и поскольку я вижу, что это своего рода головоломка, я предлагаю вам ниже код, который имеет только один рекурсивный вызов, а не два рекурсивных вызова, как в вашем коде. .

Я думаю, что это так же просто, как и при соблюдении ограничений.

Что он делает: он считает оба числа до нуля и проверяет, какое из них достигнет нуля первым. Если оба достигают нуля одновременно, результат должен быть ложным, но простая проверка того, равен ли y нулю, уже включает эту проверку.

public static boolean isLessThan(int x, int y) {
    if (y == 0) {
        return false;
    }
    if (x == 0) {
        return true;
    }

    return isLessThan(x - 1, y - 1);
}

Ответ @Andreas более эффективен, чем приведенный выше. Изначально моей целью был короткий и четкий ответ. Я попытался создать более короткий подход к битовому смещению. Хотя его труднее понять, чем пример с подсчетом, он имеет лучшую сложность и имеет такое же количество строк, как и приведенный выше код (я не считаю эту константу, поскольку я мог бы включить ее в код за счет удобочитаемости).

Обратите внимание, что этот код сдвигается влево, а не вправо, и сначала проверяется старший бит.

public static final int HIGH_BIT = 1 << 31;

public static boolean isLessThan(int x, int y) {
    if (x == y) {
        return false;
    }
    if ((x & HIGH_BIT) != (y & HIGH_BIT)) {
        return (y & HIGH_BIT) == HIGH_BIT;
    }
    return isLessThan(x << 1, y << 1);
}

Примечание: если != запрещено, вы можете изменить второй оператор if на:

if (((x ^ y) & HIGH_BIT) == HIGH_BIT)

Также обратите внимание, что сложность действительно O(1), хотя алгоритм теоретически O(log n), целые числа Java составляют 32 бита, поэтому верхняя граница O(32), что совпадает с O(1).

person Erwin Bolwidt    schedule 22.10.2017
comment
Большое спасибо, я думаю, что я слишком много думал об этом. - person Sarim A.; 22.10.2017
comment
Что делать, если задано отрицательное значение x или y? - person Erfan Ahmed; 22.10.2017
comment
@ErfanAhmedEmon См. правило 3: x и y всегда будут равны 0 или больше - person Andreas; 22.10.2017
comment
ой! моя вина. Извините, что упустил это из виду. - person Erfan Ahmed; 22.10.2017
comment
@Andreas Забавно, у моей машины Тьюринга нет проблем с запуском кода ;-) Я думаю, что эта проблема вытекает из требований, но я был бы рад проголосовать за ответ, который обрабатывает это (помимо включения проверки для x == y так как это не поможет (40000, 40001)). И в любом случае я мог бы серьезно запустить его с (40000, 40000), указав -Xss1G в командной строке. - person Erwin Bolwidt; 22.10.2017
comment
(x & HIGH_BIT) != (y & HIGH_BIT) можно заменить на (x ^ y) & HIGH_BIT - person phuclv; 23.10.2017

Вы можете сделать это как ответ на этот вопрос:
Побитовые операции, эквивалентные больше, чем оператор

Однако это не соответствует правилу 2: это должно быть рекурсивным.

Согласно комментарий, правило 1 должно быть таким:

  1. Вы можете использовать только операторы плюс, минус, умножить, равно и побитовый. .

С помощью оператора сдвиг вправо мы можем получить решение за время O(log n), в отличие от ответ Эрвина Болвидта, что занимает O(n) время и может привести к StackOverflowError.

public static boolean isLessThan(int x, int y) {
    return compare(x, y) == -1;
}

private static int compare(int x, int y) {
    if (x == y)
        return 0;  // x == y
    if (x == 0)
        return -1; // x < y
    if (y == 0)
        return 1;  // x > y

    // Compare higher bits. If different, then that is result
    int cmp = compare(x >> 1, y >> 1);
    if (cmp != 0)
        return cmp;

    // Only bit 0 differs, so two choices:
    //   x0 == 1 && y0 == 0 -> return 1
    //   x0 == 0 && y0 == 1 -> return -1
    return (x & 1) - (y & 1);
}

Если != не разрешено, код можно изменить на:

// same code up to and including recursive call
if (cmp == 0)
    return (x & 1) - (y & 1);
return cmp;
person Andreas    schedule 22.10.2017
comment
Это действительно более эффективная рекурсивная реализация +1. - person Erwin Bolwidt; 23.10.2017