У тебя O(n) здесь по двум причинам: - Константы всегда отбрасываются O(2n) -> O(n) - У тебя только один цикл из N, второй - константа
Плюс мы не можем считать от 00.00.0000, т.к. по Григорианскому календарю первый год это 1, то же самое по дням. Стартовая дата 01.01.0001
Подразумеваем, что начальная и конечная дата это 00:00 по времени, т.е. если сейчас 02.01.0001, то прошел 1 целый день с момента 01.01.0001
Высокосный год, это год, который либо делится нацело на 400, либо делится нацело на 4 и НЕ делится нацело на 100. Можно записать так: ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)
Чтобы не перечислять все года, можно посчитать, сколько высокосных лет прошло с самого начала исходя из того, что мы знаем выше: (numOfYears / 4) - (numOfYears / 100) + (numOfYears / 400)
Здесь numOfYears это количество прошедших лет. Мы включаем каждый 4-й год, исключаем каждый 100-й год и включаем каждый 400-й год. То есть если текущий год 5, то прошло целых 4 года. Из них 1 будет высокосным.
В конечном итоге мы умножаем кол. высокосных лет на 366, а не высокосных на 365. Далее добавляем количество прошедших дней в зависимости от месяца, текущий день и еще +1 день, если текущий год высокосный и текущий месяц > 2 (после февраля).
>>2897709 Технически мы можем взять и 0 год, как высокосный, тогда нужно сделать +1 в методе getNumOfLeapYears и numOfYears сделать равным year а не year - 1
>>2897709 Спасибо за отклик. Однако, твой код не проходит эти тесты: [изображение assert-ов]
Я переделал get_day_num так, как это сделал ты, но все ровно не прошло. И кстати, я дополнительно проверяю если yyyy делится на 4000 (если делится - не высокосный год).
>>2897734 Так сказано в одной задаче, которую я пытаюсь решить.
"Правила високосного года по григорианскому календарю:
годы вообще не являются високосными, за исключением кратных 4, которые являются високосными годами, за исключением кратных 100, которые не являются високосными годами, за исключением високосных годов, кратных 400, за исключением кратных 4000, которые не являются високосными."
>>2897765 Не дочитал за "которые не являтся". Непонятно откуда они взяли (в вики например нет такого, только 4, 100 и 400), но если им так надо, то пусть будет, похуй. В тестах таких кейсов это еще не встречалось.
>>2897764 Задание требует найти количество дней в промежутке между точками включительно. Я, когда переписывал тесты для этого треда, забыл прибавить 1 ко всем assert-ам, потому что в сурс файле я это делал в другой функции. То есть тупо забыл прибавить 1, когда переписывал.
Тем не менее, даже если прибавить 1 ко всем assert-ам, то с этими тестами прекрасно справляется тот алгоритм на O(n), а O(1) ломается на некоторых из них.
>>2897717 Здесь я кстати ошибся немного, в добавок ко всем правкам нужно еще в методе getNumOfLeapYears() минуснуть numOfYears на 1 перед вычислениями.
Интуиция такая, что если год 4 сейчас, то с нулевого прошло тоже 4, но высокосный должен быть 1 а не 2, потому что года 0, 1, 2, 3, а функция заточена под 0, 1, 2, 3, 4.
>>2897709 А есть ли возможность узнать количество рабочих дней между двумя точками (включительно) за O(1)?
Судя по условиям, рабочие дни - это дни с понидельника до пятницы. Также мы учитываем доп. выходные (каникулы), а именно: 1-го Января, 1-го Мая, 8-го Мая, 5-го Июля, 6-го Июля, 28-го Сентября, 28-го Октября, 17-го Ноября, 24-го Декабря, 25-го Декабря и 26-го Декабря.
Опять же, мы учитываем высокосный год.
Мой алгоритм кажется не очень эффективным. Да, он работает прекрасно, но недостаточно оптимально.
Функции, использованные в get_working_days говорят сами за себя, что они делают.
>>2897886 Ну логика здесь примерно та же самая, что и с обычными днями, но чуть посложнее.
Допустим возьмем пример проще для начала - стартовая дата всегда 01.01.0001. Мы точно так же можем посчитать количество выходных - взять количество недель, вычесть из них N выходных дней и т.д. Далее пробить по IFу на каждый особый праздник, типа если текущий день > определенного, то добавляем еще один праздник (как с высокосным годом и февралем в начале было).
Сложность кажется в том, что начало идет не всегда от 01.01.0001. Но здесь все просто вроде. Берешь считаешь количество выходных от 01.01.0001 до стартовой даты. Потом так же считаешь до конечной даты. А потом вычисляешь разницу. Т.е. получаешь промежуток между этими датами.
Пытаюсь конверитровать yyyy mm dd в количество дней от 0000 00 00.
Парочку тестов проходит, но не все. Я использую иной метод, но он имеет сложность O(2n).
Кто-нибудь знает как я могу пофиксить эту дыру и сделать ее O(1) ?
На картинке 2 функции, тот что ниже - сломанный O(1), а выше O(2n)
Высокосный год учитывается!!!