Неожиданное поведение с вложенными операторами if в С#

Я решал задачу по лит-коду № 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.


1
83
2

Ответы:

Если бы не ветка 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, ничего не произойдет.