Я решал задачу по лит-коду № 553 (просто учился), и у меня возникли проблемы с ограничениями по времени. Я передал свой код ChatGPT, чтобы узнать, как его оптимизировать, и он дал мне этот код:
public bool CheckSubArraySumV2(int[] nums, int k)
{
if (nums.Length < 2) return false;
Dictionary<int, int> sums = new()
{
[0] = -1
};
int sum = 0;
for(int i = 0; i < nums.Length; i++)
{
sum += nums[i];
int remain = sum % k;
if (sums.ContainsKey(remain))
{
if (i - sums[remain] > 1)
{
return true;
}
}
else{
sums[remain] = i;
}
}
return false;
}
После того, как я понял этот метод, я скопировал все, кроме этого вложенного оператора if:
if (sums.ContainsKey(remain))
{
if (i - sums[remain] > 1)
{
return true;
}
}
Я изменил это на это:
if (sums.ContainsKey(remain) && i - sums[remain] > 1)
{
return true;
}
но по какой-то причине в тестовом примере с nums = [5,0,0,0]
и k = 3
я получил неправильный ответ (false
вместо true
).
После нескольких попыток я решил заменить &&
back на вложенный оператор if, и по какой-то причине это работало нормально.
Мой вопрос: в чем разница между проверкой условия «&&» и вложенным оператором if? Разве он не работает от короткого замыкания?
🤔 А знаете ли вы, что...
С C# легко создавать графические приложения с помощью Windows Forms и WPF.
Если бы не ветка else
, ваш рефакторинг был бы правильным, но существование else
меняет дело.
В исходном коде сначала оценивается условие sums.ContainsKey(remain)
. Если это false
, выполняется ветвь else
.
После замены вложенных if
на составное условие с &&
значение меняется — сначала оценивается sums.ContainsKey(remain)
. Если это false
, блок else
выполняется — пока все хорошо. Однако если это true
, то оценивается условие i - sums[remain] > 1
, а если false
, то все составное выражение также false
, поэтому ветвь else
снова выполняется.
Если внимательно посмотреть на код, рассматривая эти случаи более широким взглядом
Дело 1
if (sums.ContainsKey(remain)) {
if (i - sums[remain] > 1) {
return true;
}
} else {
sums[remain] = i;
}
Случай 2
if (sums.ContainsKey(remain) && i - sums[remain] > 1) {
return true;
} else {
sums[remain] = i;
}
Вы поймете, что в первом случае код перейдет в блок else только в том случае, если нижеприведенное условие верно.
sums.ContainsKey(остается)
Во втором случае код все равно будет переходить в условие else, если вышеуказанное условие не выполнено, но из-за условия && if
я - суммы [остаются] > 1
результаты ложны, тогда код также перейдет в условие else, но если это условие не выполнено в случае 1, ничего не произойдет.