Обратите внимание, что ||
имеет короткое замыкание, т. Е. В a || b
, если a
истинно, b
не оценивается.
Разница между двумя операндами ||
является то, что existsSum(arr, n-1, sum-arr[n-1])
«добавляет» текущий элемент в список элементов, который суммируется с общей суммой, а existsSum(arr, n-1, sum)
нет.
В первом фрагменте кода, если existsSum(arr, n-1, sum-arr[n-1])
истинно, existsSum(arr, n-1, sum)
даже не вызывается. Представьте, что я вызываю это с массивом [1,2,3]
и суммой 6. Первый операнд будет возвращать true при каждом рекурсивном вызове, и нет необходимости оценивать второй операнд.
Аналогично, во втором фрагменте кода сначала запускается existsSum(arr, n-1, sum)
, а если true, existsSum(arr, n-1, sum-arr[n-1])
не вызывается. Однако existsSum(arr, n-1, sum)
редко может возвращать true самостоятельно . Под этим я подразумеваю, что для вызова existsSum(arr, n-1, sum)
, возвращающего значение true, значение true
должно быть получено из рекурсивного вызова existsSum(arr, n-1, sum-arr[n-1])
. Вы можете убедиться в этом, проанализировав различные ветви. (две ветви, которые возвращают true, это sum==0
и arr[n-1] == sum
. Надеемся, вы согласитесь, что обе встречаются редко) Это означает, что возврат (то есть вызов existsSum(arr, n-1, sum-arr[n-1])
) обязательно произойдет для existsSum(arr, n-1, sum)
.
В худшем случае эти два фрагмента кода совпадают.